繁体   English   中英

优化在Sql server中快速运行的LINQ查询?

[英]Optimize LINQ query that runs fast in Sql server?

我想计算相关表的行:

MainTable tbl = tblInfo(id);
var count = tbl.Related_Huge_Table_Data.Count();

问题是:这需要太长时间(大约20秒)才能执行,尽管当我在Sql Server中运行此查询时,它执行时间不到一秒钟。 如何在linq中优化此查询? 我也试过使用存储过程,但没有运气。

这是tblInfo方法:

public MainTable tblInfo(int id)
{
    MyDataContext context = new MyDataContext();
    MainTable mt = (from c in context.MainTables
                    where c.Id == id
                    select c).SingleOrDefault();
    return mt;
}

我使用LinqToSql,类由LinqToSql生成。

通过运行SingleOrDefault()您可以执行查询,然后必须在内存中处理结果。 您需要保持IQueryable直到您的查询完全构建。

回答“父记录有多少个子记录”的最简单方法是从子方面接近它:

using (var dx = new MyDataContext())
{
    // If you have an association between the tables defined in the context
    int count = dx.Related_Huge_Table_Datas.Where(t => t.MainTable.id == 42).Count();

    // If you don't
    int count = dx.Related_Huge_Table_Datas.Where(t => t.parent_id == 42).Count();
}

如果你坚持父方方法,你也可以这样做:

using (var dx = new MyDataContext())
{
    int count = dx.MainTables.Where(t => t.id == 42).SelectMany(t => t.Related_Huge_Table_Datas).Count();
}

如果你想在像tblInfo这样的函数中保留这个查询的一部分,你可以,但你不能从这个函数内部实例化MyDataContext ,否则在尝试将查询与另一个MyDataContext实例一起使用时会遇到异常。 因此要么将MyDataContext传递给tblInfo要么使tblInfo成为partial class MyDataContext的成员:

public static IQueryable<MainTable> tblInfo(MyDataContext dx, int id)
{
    return dx.MainTables.Where(t => t.id == id);
}

...

using (var dx = new MyDataContext())
{
    int count = tblInfo(dx, 42).SelectMany(t => t.Related_Huge_Table_Datas).Count();
}

试试这个

MyDataContext context = new MyDataContext();
var count=context.Related_Huge_Table_Data.where(o=>o.Parentid==id).Count();

//or

int count=context.Database.SqlQuery<int>("select count(1) from Related_Huge_Table_Data where Parentid="+id).FirstOrDefault();

如果您希望充分利用SQL数据库的性能,直接查询它而不是使用Linq可能是有意义的。 应该相当多的执行:)

 var Related_Huge_Table_Data = "TABLENAME";//Input table name here
 var Id = "ID"; //Input Id name here     
 var connectionString = "user id=USERNAME; password=PASSWORD server=SERVERNAME; Trusted_Connection=YESORNO; database=DATABASE; connection timeout=30";

 SqlCommand sCommand = new SqlCommand();
 sCommand.Connection = new SqlConnection(connectionString);
 sCommand.CommandType = CommandType.Text;
 sCommand.CommandText = $"COUNT(*) FROM {Related_Huge_Table_Name} WHERE Id={ID}";
 sCommand.Connection.Open();

 SqlDataReader reader = sCommand.ExecuteReader();
 var count = 0;
 if (reader.HasRows)
 {
     reader.Read();
     count = reader.GetInt32(0);
 }
 else
 {
      Debug.WriteLine("Related_Huge_Table_Data: No Rows returned in Query.");
 }
 sCommand.Connection.Close();

尝试这个:

MyDataContext context = new MyDataContext();
var count = context.MainTables.GroupBy(x => x.ID).Distict().Count();

在许多情况下,GSerg的答案是正确的。 但是当你的表开始变得非常庞大时,即使是SQL Server中的Count(1)也很慢。

解决这个问题的最佳方法是直接查询数据库统计信息,这对于Linq来说是不可能的(或者我不知道)。

您可以做的最好的事情是在表定义上创建一个静态子(C#),它将返回以下查询的结果:

SELECT 
    SUM(st.row_count)
FROM 
    sys.dm_db_partition_stats st
WHERE 
    object_name(object_id) = '{TableName}' 
    AND (index_id < 2)

其中{TableName}是表的数据库名称。

请注意它只是对计算表中所有记录的情况的答案!

您的linq2sql是否返回记录集然后在本地执行.Count(),还是将SQL发送到服务器以在服务器上进行计数? 那里的表现会有很大差异。

另外,您是否检查了执行查询时生成的SQL? 从内存中,Linq2Sql允许您检查SQL(可能是通过在您的类上设置记录器?)。 在Entity Framework中,您可以在调试和检查IQueryable <>对象时看到它,不确定Linq2Sql中是否存在等效项。

在Visual Studio中查看LINQ执行的SQL的方法?

或者,使用SQL Server Profiler(如果可用),或以某种方式查看正在执行的内容。

您可以尝试以下方法: -

  var c = from rt in context.Related_Huge_Table_Data
    join t in context.MainTables
    on rt.MainTableId ==t.id where t.id=id
    select new {rt.id};

   var count=c.Distict().Count();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM