【问题标题】:SQL Server: How does the type of an index affect a join's performance?SQL Server:索引的类型如何影响连接的性能?
【发布时间】:2011-01-04 15:41:19
【问题描述】:

如果我试图从查询中挤出最后一滴性能,那么我的联接使用这些类型的索引会产生什么影响。

  • 聚集索引。
  • 非聚集索引。
  • 具有额外列的聚集或非聚集索引可能不参与联接。

如果我创建只包含联接中涉及的列而不包含其他内容的聚集索引,我会获得任何性能吗?

(我意识到我可能不得不从另一个索引中移动聚集索引(使该索引成为非聚集索引),因为它只能有一个。)

【问题讨论】:

  • 拥有表定义和您尝试执行的连接会很有帮助。名称并不重要,但您加入的字段、您选择的字段以及表中每个字段的大小都会影响答案。
  • 我正在寻找一个一般性的答案。该查询非常具体,并且针对非常未规范化的数据库。但我会在下面发布它作为答案。

标签: sql-server tsql performance clustered-index


【解决方案1】:

您只会获得一个聚集索引 - 这是控制表在磁盘/内存中的物理存储的原因。

非聚集索引重复包含的字段,并带有指向具有该值的行的指针。在连接中使用的列上有一个索引应该可以提高性能。您可以通过在索引中使用“包含的列”来进一步优化 - 这会将行信息直接复制到索引中,这样可以消除必须查找行本身才能执行选择的性能损失。

注意连接发生的顺序很有用 - 索引中的列顺序应该与此匹配。请记住,SQL 引擎可能会在内部优化和重新排序您的查询 - 分析可能会有所帮助。

在大多数情况下,您可以只使用数据库引擎优化顾问 - 它提供的建议非常准确。

【讨论】:

    【解决方案2】:

    如果可以的话,最好的选择是使用包含所有联接元素的非聚集索引,如果可能,还包括您选择的字段。

    这将创建一个跨越索引,这意味着 SQL 需要执行的所有字段都在一个索引上。

    如果可能的话,有一个索引,其中没有 unnessasery 字段。添加的每个字段都会使单个索引记录更大,每个索引记录越小,您在每个页面中获得的越多。您在每个页面中获得的索引项越多,您访问磁盘的次数就越少。

    聚集索引 - 表示表格按索引中指定的顺序排列,这意味着您将获得更好的性能 select * from TABLE where INDEXFIELD = 3. 除非您选择很多大数据项,这不应该是必需的。

    【讨论】:

      【解决方案3】:

      除了 Gareth Saul 的回答之外,还有一点澄清:

      非聚集索引重复 包含的字段,指针指向 具有该值的行

      这个指向实际数据值的指针是集群键中的列(或列集)。

      这就是为什么您应该尝试保持集群密钥小而静态的主要原因之一 - 小,否则您将浪费大量空间,在磁盘和服务器的 RAM 中,并且是静态的,否则,您将如果您的值发生变化,不仅必须更新您的聚簇索引,还必须更新所有非聚簇索引。

      这种“查找指针是群集键”功能从 SQL Server 版本 7 开始就已存在,如Kim Tripp will explain in great detail here

      什么是聚集索引?

      在 SQL Server 7.0 及更高版本中 内部依赖 群集键已更改。 (是的,它是 重要的是要知道事情发生了变化 在 7.0 中...为什么?因为还有 有些人没有 意识到变革的激进程度 发生在内部(写到 集群键)在 SQL Server 7.0)。

      改变的是聚类 键被用作“查找”值 来自非聚集索引。

      【讨论】:

      • 感谢您的澄清 - 我认为索引引用是内部引用,独立于使用的集群键。很高兴学习新东西!
      • 在处理 CL 表上的 NC 索引时正确,但 Heap 上的 NC 索引仍然使用非易失性行 ID,然后表使用转发指针进行记录移动。 (这是特定于 SQL 的更新版本,2005 / 2008 而不是以前的版本)
      • @Andrew:是的,但几乎没有充分的理由拥有聚集索引 - 所以这可能是最有可能的情况。据我所知,这是在 SQL Server 7 及更高版本中 - 而不仅仅是 2005 及更高版本。请参阅 Kim Tripp 的博客文章,其中她提到了这一点:sqlskills.com/BLOGS/KIMBERLY/post/…
      • @marc_s :同意,我更喜欢从它应该有的观点开始,然后需要有理由才能没有。 CL 上的 NC 更改很早就完成了,但我不记得转发指针和从 volatile 行 id 到 non-volatile 的更改是否在那个版本中完成。
      【解决方案4】:

      如果我创建只包含连接中涉及的列而不包含其他任何内容的聚集索引,我会获得任何性能吗?

      不是我理解的。聚集索引的要点在于,它会围绕该索引对磁盘上的数据进行排序(因此为什么只能拥有一个),所以如果您的连接数据也没有按这些确切的列排序,我不会认为它会有所作为。此外,通过将可能更改的数据(而不是键)放入聚集索引中,您更有可能需要定期重建事物,从而减慢整个数据库的速度。

      抱歉,这听起来是个愚蠢的问题,但您是否尝试过通过索引调整向导运行查询?无论如何都不是万无一失的,但过去我已经有了一些不错的改进。

      【讨论】:

        猜你喜欢
        • 2011-06-25
        • 1970-01-01
        • 1970-01-01
        • 2013-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-04
        • 2010-09-12
        相关资源
        最近更新 更多