我有一个winforms应用程序,我有一个Telerik下拉列表,让用户可以选择一组州名。
使用EF和数据库存储在Azure SQL中。
然后,代码将访问大约17,000条记录的数据库,并将结果过滤为仅包括已检查的状态。
工作正常。我想在更改列表框时更新屏幕上的计数。
这是itemCheckChanged事件中的代码:
var states = stateDropDownList.CheckedItems.Select(i => i.Value.ToString()).ToList();
var filteredStops = (from stop in aDb.Stop_address_details where states.Contains(stop.Stop_state) select stop).ToArray();
ExportInfo_tb.Text = "Current Stop Count: " + filteredStops.Count();
它有效,但速度很慢。 我试图将所有内容加载到内存变量中然后查询与数据库相比,但似乎无法弄清楚如何做到这一点。
有什么建议吗?
改进: 通过限制下来的数据量,我获得了显着的改进:
var filteredStops = (from stop in aDb.Stop_address_details where states.Contains(stop.Stop_state) select stop.Stop_state).ToList();
更好 -
int count = (from stop in aDb.Stop_address_details where
states.Contains(stop.Stop_state)
select stop).Count();
ExportInfo_tb.Text = "Current Stop Count: " + count.ToString();
答案 0 :(得分:1)
在这种情况下,查询的性能实际上与Contiains
无关。包含非常高效。正如您在第三个解决方案中所提到的那样,问题在于您通过网络提取的数据远远超过了所需的数据。
在第一个解决方案中,您将从服务器中撤回具有匹配停止状态并在本地执行计数的所有行。这是最糟糕的方法。你正在撤回数据只是为了计算数据而你正在撤回远远超过你需要的数据。
在您的第二个解决方案中,您将数据限制回单个字段,这就是性能得到改善的原因。如果您的桌子很宽,这可能会带来显着的改善。这样做的问题在于,您仍在撤回所有数据,只是为了在本地计算数据。
在您的第三个解决方案中,EF会将.Count()
方法转换为为您执行计数的查询。因此计数将在服务器上发生,并且返回的唯一数据是单个值;计数的结果。由于网络延迟通常是(但并非总是)执行查询时最长的步骤,因此返回较少的数据通常可以显着提高查询速度。
最终解决方案的查询翻译应如下所示:
SELECT COUNT(*) AS [value]
FROM [Stop_address_details] AS [t0]
WHERE [t0].[Stop_state] IN (@p0)