如何加快此查询?现在,我花了大约2分钟来取回210K记录。
我关闭了LazyLoading,并在我的桌子上设置了AsNoTracking。
我知道很多数据,但肯定不需要2分钟才能检索数据?
context.Configuration.LazyLoadingEnabled = false;
List<MY_DATA> data = context
.MY_DATA.AsNoTracking()
.Include(x => x.MY_DATA_DETAILS)
.Where(x => startDate <= DbFunctions.TruncateTime(x.DB_DATE)
&& endDate >= DbFunctions.TruncateTime(x.DB_DATE)
&& x.MY_DATA_DETAILS.CODE.Trim().ToUpper() == myCode.Trim().ToUpper())
.ToList();
答案 0 :(得分:3)
您可以不使用DbFunctions.TruncateTime()
,也可以不使用这些Trim().ToUpper()
来电。
如果在筛选之前对数据库列执行函数,则查询优化器无法使用此列上的任何索引。这被称为 non-sargable 。要以当前形式执行查询,数据库引擎必须首先转换数据,然后扫描所有转换后的数据以进行过滤。没有涉及索引。
DbFunctions.TruncateTime()
毫无意义。您必须明智地选择startDate
和endDate
,并按原样使用x.DB_DATE
。
此外,如果x.MY_DATA_DETAILS.CODE
是varchar
列(大多数文字列都是),则会在搜索中对其进行自动裁剪。即使数据库值包含尾随空格,也会忽略它们。所以Trim
是不必要的。接下来,默认情况下,大多数文本列都具有不区分大小写的数据库排序规则。你应该检查一下。如果这是SQL Server,请查找SQL_Latin1_General_CP1_CI_AS
之类的排序规则。 CI
部分表示不区分大小写。如果是这样,您也可以取消ToUpper
部分。如果不是,您可以将排序规则更改为不区分大小写的排序,或者您可能因为某种原因而认为该列区分大小写,因此您是否查找{{1} }或Abc
。
无论哪种方式,从数据库列中删除这些转换函数,只要适当的索引到位,查询应该能够以相当快的速度运行。
答案 1 :(得分:2)
通常在“where”子句中经常使用的列上定义索引,可以提高从大型故事中选择行的性能。
我建议您创建存储过程并将查询移到SP中并在数据库和C#代码中应用性能调整,然后调用SP。
答案 2 :(得分:0)
您是否需要该对象的所有属性? 你可以这样做。
List<MY_DATA> data = context.MY_DATA.Include(x =>
x.MY_DATA_DETAILS).Where(x => startDate <= DbFunctions.TruncateTime(x.DB_DATE) &&
endDate >= DbFunctions.TruncateTime(x.DB_DATE) &&
x.MY_DATA_DETAILS.CODE.Trim().ToUpper() == myCode.Trim().ToUpper()).select(x => new MY_DATA()
{
Value = data
}).ToList();
答案 3 :(得分:0)
除了另一个人关于将查询移动到存储过程并创建正确索引的内容之外,我还说你最好不要使用SQL报告而不是尝试将数据导入您的申请和报告。特别是210K行。 SQL具有内部优化功能,您永远无法接近存储过程和查询。
您可以非常轻松地看到这一点:
1)尝试编写一个简单的控制台应用程序,尝试下拉整个表并将其写入CSV文件 - 它非常慢。
2)尝试通过Sql Mgmt Studio使用数据导出并导出为CSV - 它将在几秒钟内完成。