我需要将10,000到20,000个唯一过滤器应用于50M行的数据集,其中包含8列和正确的索引。
我目前的方法是一次一个地动态生成和执行这些查询:
var stats = (from a in db.AggregatedStats
where a.StatType.StartsWith("TOTAL_ITEM")
select a);
// Add more filters to the WHERE clause
foreach (var stat in stats) { // Process the data }
我相信这种方法称为“流”数据从SQL Server到MoveNext()。
将数据缓冲到程序的内存中会更有效吗?
var stats = (from a in db.AggregatedStats
where a.StatType.StartsWith("TOTAL_ITEM")
select a).ToList();
然后将过滤器应用于此实体列表:
var result = (from a in stats
where a.Region.Equals(region)
select a);
这样可以有效地将SQL Server查询的数量从10,000减少到1。
在这种情况下,与从10,000个查询中流式传输数据所花费的时间相比,将数据集缓冲到程序中是否值得额外的RAM?
谢谢!
答案 0 :(得分:2)
否定。将数据库中的枚举推迟到最后一个可能的秒数消除了您将获得无效的数据推送到内存中(这只会使用于此应用程序的内存膨胀)。这是您当前样本使用的方法(因为它实际上在foreach
开始之前不会被调用)并且应该是最高效的。
我想你可能会感到困惑;当你写作
var stats = (from a in db.AggregatedStats
where a.StatType.StartsWith("TOTAL_ITEM")
select a);
实际上没有发生任何事情 - stats
只包含一个知道如何获取数据的迭代器,在您使用ToList()
调用foreach
或枚举该查询之前,实际上并未请求任何内容这就是你获得表现的原因。
答案 1 :(得分:2)
我需要一些时间来分析这些过滤器,看看哪些过滤掉了大部分数据。您可能会发现有10-20个过滤器可以过滤掉95%的数据。
如果您可以识别过滤掉大部分数据的前X个过滤器,那么您可以将这些过滤器的查询应用于数据库。你得到的结果将是一组有限的记录,你可以缓冲并在内存中进行过滤。