【发布时间】:2015-06-26 21:55:02
【问题描述】:
困境
我有一个大型数据集,我需要对其中的一部分执行复杂的计算。对于我的计算,我需要根据输入参数从一个大集合中获取一个有序数据块。
我的方法签名如下所示:
double Process(Entity e, DateTimeOffset? start, DateTimeOffset? end)
可能的解决方案
想到以下两种方法:
方法 1 - WHERE 子句
double result = 0d;
IEnumerable<Quote> items = from item in e.Items
where (!start.HasValue || item.Date >= start.Value)
&& (!end.HasValue || item.Date <= end.Value)
orderby item.Date ascending
select item;
...
return result;
方法 2 - 跳过和采取
double result = 0d;
IEnumerable<Item> items = e.Items.OrderBy(i => i.Date);
if (start.HasValue)
items = items.SkipWhile(i => i.Date < start.Value);
if (end.HasValue)
items = items.TakeWhile(i => i.Date <= end.Value);
...
return result;
问题
如果我只是把它放在一起,我可能会选择方法 1,但是我的数据集的大小和数据集的大小都太大而无法忽略效率损失,并且对生成的可枚举项进行排序至关重要。
哪种方法会产生更有效的查询?还有没有更有效的方法我还没有考虑?
提出的任何解决方案都可以安全地假设该表已被良好索引。
【问题讨论】:
-
您应该使用 IQueryable
- 来确保生成 SQL 并且数据集没有加载到内存中。您可以尝试使用 SQL 分析器查看生成的 SQL 并在您的服务器上运行它以查看执行时间。
-
IQueryable 很好。我应该比那更清楚。基于此修复了问题。
-
Aaa 然后我回滚,意识到 IQueryable 不能与 orderby 配合使用。不过,我确实确认它没有提前评估。
-
因为您在 DateTime 上使用 .Date,这是本机 C# 代码,需要加载到 CLR 中,因此永远不会在 SQL 中运行。您应该使用 EntityFunctions 在 OrderBy msdn.microsoft.com/en-us/library/… 中创建一个没有时间的日期
-
其实我不是。您正在查看的是假设类
Item的Date属性。它是DateTimeOffset类型,正如方法签名所暗示的那样。DateTimeOffset将被 SQL Server 巧妙地处理。
标签: c# linq entity-framework entity-framework-6