在已经投入生产的WPF应用程序中,用户有一个窗口,用于选择客户端。它显示了包含所有客户端的列表和一个可以搜索客户端的TextBox。
随着客户群的增加,这种速度异常缓慢。大约1分钟的操作,每天发生约100次。
目前,MSSQL管理工作室表示查询select id, name, birth_date from client
需要41秒才能执行(大约130000行)。
对于如何改善这段时间有什么建议吗?代码上的索引,ORM或直接sql查询?
目前我正在使用框架3.5和LinqToSql
答案 0 :(得分:4)
如果您的查询实际上是SELECT id, name, birth_date from client
(即没有where子句),那么您可以做的很少,以加快新硬件的速度。 SQL Server必须进行表扫描才能获得所有数据。即使覆盖索引也意味着它必须扫描与表一样大的索引。
您需要问自己的是:130000个客户列表对您的用户真正有用吗?我真的要滚动到列表中的第75613条,找到他们想要的用户吗?答案可能不是。我只会选择搜索选项。至少那时你可以添加对这些查询有意义的索引。
如果您确实需要整个列表,请尝试以块的形式加载它。从前500条记录开始,然后在用户移动滚动条时添加更多记录。这样就减少了初始加载时间,用户只会加载必要的数据。
答案 1 :(得分:3)
为什么需要所有客户的清单?你不能只是拥有你描述的搜索TextBox并在服务器端处理搜索查询。在那里,您为单个客户端搜索的最大返回行数设置上限(例如,最多500个匹配)。
或者,可以通过在Web服务器上缓存客户端数据列表来获得一些效率提升
答案 2 :(得分:2)
根据您的查询,索引不应该有用。您可以使用一个缓存已排序查询的视图(假设您没有按ID排序?),但鉴于SQL Server的adhoc查询的烘焙查询缓存,您可能不会在那里看到太大的收益。 ORM确实增加了一些开销,但有几个教程可以降低成本(例如http://www.sidarok.com/web/blog/content/2008/05/02/10-tips-to-improve-your-linq-to-sql-application-performance.html)。适用于您的要点是尽可能使用已编译的查询,并为只读数据关闭乐观并发。
通过让您的客户不直接点击数据库,可以实现更大的性能提升。如果你在那里添加一个服务层(不一定是web服务,但它可能是),那么服务类或应用程序可以放置一些智能缓存,这对于像这样的只读查询有一个数量级的帮助。
答案 3 :(得分:1)
进入SQL Server,进行新的查询。在“查询”菜单中,单击“包括客户端统计信息”。
运行查询就像在代码中一样。 它将显示结果以及名为“客户统计”
的结果旁边的选项卡点击它并查看“服务器回复的等待时间”中的时间。这是ms,这是服务器实际执行的时间。
我刚刚运行了这个查询:
select firstname, lastname from leads
服务器上花了3ms来获取301,000条记录。
“总执行时间”类似于483ms,其中包括SSMS实际获取数据并处理数据的时间。我的查询需要2.5-3s才能在SSMS中运行,剩下的时间(2500ms左右)实际上是SSMS绘制结果等。)
我的猜测是,41秒可能没有花在SQL服务器上,因为130,000条记录确实不是那么多。在SQL服务器返回结果之后,41秒可能主要用于所有内容。
如果发现SQL Server需要很长时间才能执行,请在查询菜单中启用“包含实际执行计划”,然后重新运行查询。出现一个名为“执行计划”的新选项卡,此选项卡将显示当您对此表执行选择时SQL服务器正在执行的操作以及它花费所有时间的百分比。就我而言,它在100%的时间内用于PK_Leads的“聚集索引扫描”
已修改为包含更多统计资料
答案 4 :(得分:0)
一般来说:
但:
在您的情况下,它看起来像查询是全表扫描,这对性能无益,请检查您是否确实需要一次检索所有这些数据。
由于没有任何条款,因此查询执行不太可能是问题所在。意味着其他索引无济于事。
您需要更改应用程序访问数据的方式。不是将所有客户端加载到内存中,然后在内存中搜索它们,而是需要将搜索项传递给数据库查询。
LinqToSql使您可以使用不同的功能来搜索值,这里有一个描述其中大部分的博客: http://davidhayden.com/blog/dave/archive/2007/11/23/LINQToSQLLIKEOperatorGeneratingLIKESQLServer.aspx