【发布时间】:2010-09-08 19:52:29
【问题描述】:
我知道这是一个宽泛的问题,但我继承了几个表现不佳的人,需要对它们进行严重优化。我想知道优化所涉及的最常见步骤是什么。那么,你们中的一些人在面对同样的情况时会采取什么措施呢?
相关问题:
What generic techniques can be applied to optimize SQL queries?
【问题讨论】:
-
看起来很像this older question。
我知道这是一个宽泛的问题,但我继承了几个表现不佳的人,需要对它们进行严重优化。我想知道优化所涉及的最常见步骤是什么。那么,你们中的一些人在面对同样的情况时会采取什么措施呢?
相关问题:
What generic techniques can be applied to optimize SQL queries?
【问题讨论】:
【讨论】:
SET AUTOTRACE ON)。这会让你看到物理读取等内容。不过,我只会在遵循 roman 的建议后使用它。
在 SQL Server 中,您可以在查询分析器或 Management Studio 中查看查询计划。这将告诉您在每批语句中花费的时间的粗略百分比。您需要查找以下内容:
其他一些一般提示:
最后,我强烈建议您创建一组负载测试(使用 Visual Studio 2008 测试版),您可以使用它们来模拟您的应用程序在处理大量请求时的行为。一些 SQL 性能瓶颈仅在这些情况下才会显现出来,并且能够重现它们使得修复起来容易得多。
【讨论】:
索引可能是一个很好的起点......
SQL Server 索引 Tuning Wizard 可以解决低悬的果实。
【讨论】:
我不确定其他数据库,但对于 SQL Server,我推荐执行计划。它非常清楚(尽管有很多垂直和水平滚动,除非你有一个 400 英寸的显示器!)显示你的查询的哪些步骤正在消耗时间。
如果你有一个步骤需要疯狂的 80%,那么也许可以添加一个索引,然后在调整索引后,重新运行执行计划以找到你的下一个最大步骤。
经过几次调整后,您可能会发现确实没有任何步骤可以从其他步骤中脱颖而出,即每个步骤都是 1-2%。如果是这种情况,那么您可能需要查看是否有方法可以减少查询中包含的数据量,是否需要将这四百万已关闭的销售订单包含在“活动销售订单”查询中?不,所以排除所有具有 STATUS='C' ... 或类似内容的人。
您将从执行计划中看到的另一个改进是书签查找,基本上它在索引中找到匹配项,但是 SQL Server 必须快速遍历表以找到您想要的记录。此操作有时可能比首先扫描表所花费的时间更长,如果是这种情况,您真的需要该索引吗?
对于索引,特别是对于 SQL Server 2005,您应该查看 INCLUDE 子句,这基本上允许您在索引中拥有一列而不真正在索引中,所以如果您查询所需的所有数据都在如果您的索引或者是包含的列,那么 SQL Server 甚至不必查看表,这是一个很大的性能提升。
【讨论】:
您可以通过以下几个方面来优化查询性能。
确保您只有最少的数据。确保仅选择所需的列。将字段大小降至最低。
考虑对数据库进行反规范化以减少连接
避免循环(即获取游标),坚持设置操作。
将查询实现为存储过程,因为这是预编译的,执行速度更快。
确保设置了正确的索引。如果您的数据库主要用于搜索,请考虑更多索引。
使用执行计划查看处理是如何完成的。您要避免的是表扫描,因为这很昂贵。
确保自动统计设置为开启。 SQL 需要它来帮助确定最佳执行。有关更多信息,请参阅 Mike Gunderloy 的精彩帖子。 Basics of Statistics in SQL Server 2005
确保您的索引没有碎片Reducing SQL Server Index Fragmentation
确保您的表没有碎片。 How to Detect Table Fragmentation in SQL Server 2000 and 2005
【讨论】:
执行计划是一个很好的开始,它将帮助您确定需要处理的查询部分。
一旦你弄清楚了在哪里,就该解决如何以及为什么了。查看您尝试执行的查询类型。不惜一切代价避免循环,因为它们很慢。不惜一切代价避免使用游标,因为它们很慢。尽可能坚持基于集合的查询。
如果您正在使用连接,有一些方法可以为要使用的连接类型提供 sql 提示。不过请注意,虽然一个提示可能会加快您的查询一次,但它可能会在下一次根据数据和参数将您的查询减慢 10 倍。
最后,确保您的数据库索引良好。一个好的起点是包含在 where 子句中的任何字段可能应该有一个索引。
【讨论】:
查看进行查询的表上的索引。参与 where 子句的特定字段可能需要索引。还要查看查询中连接中使用的字段(如果存在连接)。如果索引已经存在,请查看索引的类型。
失败(因为使用锁定提示有负面影响)查看锁定提示并明确命名要在连接中使用的索引。如果您遇到大量死锁事务,则使用 NOLOCKS 会更加明显。
尽管按照 roman 和 Andy S 首先提到的方式去做。
【讨论】: