Answers:
查询调整101
尽管我可以为您提供一些提示和技巧,但没有任何灵丹妙药可用于查询调优。首先要做的是了解幕后的实际情况。获得良好的内部书籍,例如第三本《大师指南》。
表现不佳的查询通常有两个基本方面:事务查询花费的时间太长,以及研磨批处理作业(或报告)的时间太长。查询有问题的一个好兆头是查询计划中的一项花费了99%的时间。
交易查询
在大多数情况下,性能不佳的事务查询是以下几项之一:
缺少索引。您可以在查询计划中看到这一点-联接中大型表的表扫描应该非常有选择性(即返回几行)。
查询无法使用索引。如果where子句中具有OR条件,并连接查询中不可计算的计算值或其他项目,则可能需要重新编写查询。简而言之,Sarg是查询谓词,可以使用索引来消除行。逻辑AND,相等和不等式(>,> =,<,<=和!=)都是可保留的。OR在传统上是不可保留的。但是,您通常可以通过将“或”的含义从“或”转换为“非”(foo和not bar)类型构造,从而将“或”转换为可保留谓词。
无效的谓词。例如,如果您有一个where in
嵌套子查询的引用,请查看该子查询是否可以重写为where exists
或联接。这可能会导致更有效的查询计划,这是您可以尝试的其他标准重写。再次,大师的指导书和其他有关该主题的书是一个很好的起点。
批量查询
批查询更为复杂,并且存在不同的调优问题。一些提示是:
索引。出于与事务查询相同的原因,这可能会有很大的不同。索引丢失的一个好兆头通常是长时间的磨削操作(占查询计划的99%),但这似乎并没有使机器受到影响。
临时表。您可能会发现将一个查询分解为几个填充临时表的查询会更好。较大的查询为优化器提供了更多的解决空间,尽管这已不再是以前的问题。使用select into
此操作记录的临时表最少(少了日志活动),从而减少了I / O负载。
请注意,tempdb中的临时表与优化程序用于存储中间联接结果的数据结构相同,因此这样做不会对性能造成任何影响。您还可以在临时表上创建索引(包括聚集索引和覆盖索引),其原因可能与提高对静态表的查询的原因相同,因此可以提高读取该查询的性能。
但是不要过度使用临时表,因为它们会使查询变得更难追溯。对于存储过程中的较小表,请测试以查看表变量是否有帮助。这些是内存中的数据结构,因此可以赢得性能。
聚集和覆盖索引。由于它们可以根据某些分组列在磁盘上强制引用局部性,因此可以提高查询的性能。聚集索引可以对批处理作业的性能产生很大的影响。
低效的谓词。这些可能会导致sargs和其他子优化问题,其方式与处理事务查询时几乎相同。
表扫描是您的朋友。与普遍的看法相反,表格扫描并不是天生的邪恶。通常,它们表示事务查询中出现了问题,但是它们通常是执行大型批处理操作的最有效方法。如果您要执行的操作超过了表中百分之几的行,则表扫描通常是覆盖表的最有效方法。
嵌套循环联接。看一看优化器在连接的两边都在做什么。如果您这样做的话,这些方法可能会效率低下(例如,在嵌套循环连接的两侧扫描两个大表的表。考虑使用聚簇索引,或者order by
尝试将操作更改为合并联接,或者如果一侧是则提示提升哈希联接)小到足以做到这一点。
锁定
锁定也会导致性能问题。如果您的系统在负载下性能不佳,请查看与锁相关的事件探查器和perfmon计数器,并检查是否存在重大竞争。 sp_who2
结果集中有一个“ BlkBy”列,该列将显示查询是否被阻止以及阻止它的原因。同样,具有“死锁图”事件(如果您有查询死锁)和与锁相关的事件的配置文件对于解决锁问题也很有用。
RedGate提供的关于如何使用和理解SQL Server执行计划的优秀免费电子书
http://www.red-gate.com/specials/Grant.htm?utm_content=Grant080623
Shameless Plug,我在SQL Server Performance的博客上引用了性能调整材料。
一旦您有机会消化其中的一些材料,请随时在此处发布,或直接与我联系以提出具体问题。