【问题标题】:What do you do to make sure a new index does not slow down queries?您如何确保新索引不会减慢查询速度?
【发布时间】:2011-11-19 00:05:32
【问题描述】:

当我们添加或删除一个新索引来加速某些事情时,我们最终可能会减慢其他事情的速度。 为了防止这种情况,在创建新索引后,我正在执行以下步骤:

  1. 启动 Profiler,
  2. 运行包含大量查询的 SQL 脚本,我不想放慢速度
  3. 将跟踪从文件加载到表中,
  4. 在我添加(或删除)索引之前,根据之前运行的结果分析跟踪中的 CPU、读取和写入。

这是一种自动化,可以满足我的需求。但是,我不确定是否有更好的方法来做到这一点。有什么工具可以满足我的需求吗?

编辑 1 投票结束我的问题的人,你能解释一下你的理由吗?

编辑 2 我用谷歌搜索,但没有找到任何解释添加索引如何减慢选择的内容。然而,这是一个众所周知的事实,所以应该有什么东西在某个地方。如果什么都没发生,我可以稍后再写几个例子。

编辑 3 一个这样的例子是:两列高度相关,比如身高和体重。我们有一个关于高度的索引,它对我们的查询来说不够选择性。我们添加一个权重索引,并使用两个条件运行查询:身高范围和体重范围。因为优化器不知道相关性,它严重低估了我们查询的基数。

另一个例子是在增加的列上添加索引,例如 OrderDate,可能会严重减慢具有像 OrderDate>SomeDateAfterCreatingTheIndex 这样的条件的查询。

【问题讨论】:

  • 嗯。我可以看到 一些操作 会因添加索引而减慢速度。我不希望 查询 受到影响。在最坏的情况下,我希望只有锁定操作(插入、删除或显式锁定查询)会受到影响。
  • @sehe:添加索引会减慢选择速度。这不太可能,但有可能。
  • 一种模糊但潜在的情况是,当新索引不如以前用于查询的索引最优时,但由于统计数据过时、参数嗅探或其他可能导致优化器到错误的索引...
  • @sehe - Here is a recent example startdate 上的索引的可用性意味着选择查询比索引根本不存在时更糟糕。
  • @sehe - 更令人担忧的是,您可能还会遇到产品中的错误...Incorrect Results Caused By Adding an Index

标签: sql-server sql-server-2008 query-optimization sql-server-2008-r2


【解决方案1】:

来自“查询性能调优”页面

Improve Indexes

此页面包含许多有用的分步提示,说明如何调整索引以获得最佳性能,以及需要注意什么(分析)。

与大多数性能优化技术一样,需要权衡取舍。例如,使用更多索引,SE​​LECT 查询可能会运行得更快。但是,DML(INSERT、UPDATE 和 DELETE)操作会显着减慢,因为每个操作都必须维护更多的索引。因此,如果您的查询主要是 SELECT 语句,则更多索引可能会有所帮助。如果您的应用程序执行许多 DML 操作,您应该对创建的索引数量保持保守。

其他资源:

但是,重要的是要记住,非聚集索引会减慢数据修改和插入过程,因此应将索引保持在最低限度

SQL Server 中的分段索引和表会降低应用程序的性能。这是一个在 SQL 服务器和数据库中查找碎片索引的存储过程。

【讨论】:

  • 谢谢,但我不是在询问有关索引调整的通用指南。我的问题是关于如何有效地实施具体步骤以确保符合这些准则。因此,您的回答与我的问题不符。
【解决方案2】:

您的问题最终可以改写为“我如何确保已经使用最佳、快速计划的查询不会被“优化”为更差的执行计划?' .

无论是由于参数嗅探、统计信息更新还是元数据更改(例如添加新索引)而导致计划更改,我所知道的保持计划稳定的最佳答案是plan guides。为已经具有良好执行计划的关键查询部署计划指南可能是强制优化器继续使用良好、经过验证的计划的最佳方式。见Applying a Fixed Query Plan to a Plan Guide:

您可以将固定查询计划应用于 OBJECT 类型的计划指南或 SQL。应用固定查询计划的计划指南非常有用 了解现有执行计划的性能优于 优化器为特定查询选择的一个。

通常的警告适用于阻止优化器使用实际上可能比计划指南更好的计划的任何可能滥用功能。

【讨论】:

  • Remus,我喜欢这个主意,所以 +1。但是,我正在处理数百个模块,并寻找一种简单有效的方法来监控它们是否行为不端。即使我冻结了所有执行计划,我仍然需要监控它们是否仍然执行良好 - 冻结的计划可能会过时并适得其反。
【解决方案3】:

好的。首先,索引减慢了两件事(至少)

-> 插入/更新/删除:索引重建

-> 查询计划:“我应该使用那个索引吗?”

有人提到查询计划器可能会采用效率较低的路线 - 这不应该发生。

如果您的优化器甚至还不错,并且您的统计数据/参数正确,那么它就不会选择错误的计划。

无论哪种方式,就您的情况(mssql)而言,您几乎无法信任优化器,并且仍然必须每次都进行检查。

您目前正在做的事情看起来很合理,您应该确保您正在查看的数据是相关的,即正确比例的真实用例查询(这可以带来不同的世界)。

为了做到这一点,我总是建议编写一个基于实际使用的基准测试脚本 - 通过生产环境的日志记录。查询,有点像我在这里说的:

Complete db schema transformation - how to test rewritten queries?

【讨论】:

  • 你能告诉我哪个 RDBMS 有一个优化器,它总是生成你的答案前半部分暗示的完美计划吗?
  • 目前没有。但是,对于大多数基本任务,您可以比其他优化器更信任一些优化器,并且此处引用的有关 MSSQL 的 (WTF) 看起来与错误的统计/设置或错误的优化器有关。 PostgreSQL 优化器在我看来对任何标准都非常好,并且每天都在变得更好,从这个意义上说,我希望它失败的次数要少得多。 “不应该发生”意味着它不应该发生..我们都知道结果与意图有何不同。半体面的优化器可能不存在,但我再次对 pgsql 有一些信任。
【解决方案4】:

下面的方法怎么样:

  • 保存所有典型查询的执行计划。
  • 应用新索引后,检查哪些执行计划发生了变化。
  • 使用修改后的计划测试查询的性能。

【讨论】:

    猜你喜欢
    • 2016-08-28
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-22
    • 2011-10-04
    相关资源
    最近更新 更多