[英]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.