SQL Server 2005/8查询优化提示


13

我正在教育一个团队编写更好的SQL Server查询,并且想知道人们对提高性能的最佳提示是什么。

例如,我曾经有一个DBA坚持认为count(*)的性能会比count(1)差(我不知道她是对的还是对最新的查询优化器仍然有效)。

我应该告诉团队尝试哪些简单的事情,并始终使用或避免使用?理想情况下,我正在寻找能够(a)产生合理影响且(b)直截了当的陈述(1-2条陈述)的事物。

Answers:


13

查询调整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”列,该列将显示查询是否被阻止以及阻止它的原因。同样,具有“死锁图”事件(如果您有查询死锁)和与锁相关的事件的配置文件对于解决锁问题也很有用。


1
+1,因为这是一些有关性能调优的重要信息(我很高兴能参加Kalen的课程。她确实知道自己正在做什么!)。您可以在动态视图上添加一些信息。
韦恩,2009年

3

最佳提示:使用SQL Server 2008,并在测试运行时运行活动监视器。请注意花费时间最长/具有最大I / O的查询,等等。右键单击这些查询以查看查询和/或执行计划。

下一步:学习理解执行计划。

下一步:使用数据库调整向导。

这些步骤将帮助您生成自己的“最佳提示”。



1

首先,建立索引。许多人没有意识到外键不会自动获取索引。由于它们在联接中使用,因此它们几乎总是应该具有索引。

仔细检查所有游标,看看是否可以将其替换为基于集合的代码。通过执行此操作,我将运行了几小时到几秒钟的代码更改了。

避免子查询。如果在代码中包含它们,则将它们替换为联接或联接到派生表。

确保您的where子句可更改。

学习阅读执行计划。

确保办公室有几本关于性能调优的好书。

在某些情况下,表变量要比临时表好,而在另一些情况下,临时表的性能要好。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.