【问题标题】:Order of columns in index - insert performance索引中的列顺序 - 插入性能
【发布时间】:2013-04-22 15:40:24
【问题描述】:

我对索引列的顺序进行了一些研究,但不能 100% 确定,所以请多多包涵! 我有下表:

CREATE TABLE [Valuation]
    (  
      [ValuationID] [int] IDENTITY(1, 1)
                          NOT NULL
                          CONSTRAINT [PK_Valuation] PRIMARY KEY ,  
      VersionID INT NOT NULL ,  
      AlphanumericIdentifier VARCHAR(255) NOT NULL,  
      ...  
      other columns  
      ...  
    )  

我在这张表上对 VersionID 和 AlphanumericIdentifier 上的其他人做了很多连接,所以我在上面放了一个索引:

CREATE NONCLUSTERED INDEX [IX_Valuation] ON [dbo].[Valuation]   
(
[VersionID] ASC,
[AlphanumericIdentifier] ASC
)

两个问题:

  1. 这些连接通常针对特定的 VersionID 完成,因此这是最具选择性的列,应该是索引中的第一个列 - 对吗?
  2. 插入总是针对单个版本完成,比上一个版本多 1 个。这应该可以减轻对插入的性能影响,因为插入的行是可以添加到索引末尾的“块”。对吗?

我很确定我在 1 上是对的,但在 2 上是正确的吗?

谢谢 乔

【问题讨论】:

  • 您在使用身份列吗? VersionID + Alphenumericidentifier 的组合是否唯一?如果实际上不会使用它,也许您应该考虑两列上的 PK 而不是标识列上的 PK。
  • 听起来VersionID 应该是PK(和身份)
  • VersionID + Alphenumericidentifier 不是唯一的。它们应该与另一个 varchar 字段一起是唯一的,但由于涉及的风险,我无法在项目的这个阶段引入唯一索引。但是,如果我可以让时间倒流,这听起来是个好主意……另一个限制是我需要在文件中向第 3 方供应商发送一个唯一 ID。这将是多达 10+255+255=560 个字符,这可能会给他们带来问题。目前我们只是向他们发送一个 int PK,最多 10 个字符就可以了
  • 永远不要为了时间而接受糟糕的设计。以后你只会花越来越多的时间去考虑它,而不是一发现问题就去纠正这艘船。
  • @AaronBertrand - 同意。源系统是一个数据库,但没有约束。我们可以而且应该在导入数据时强制执行约束,例如使用 max() 或 sum() 来处理欺骗。不久前我认为唯一索引在插入时的性能命中比非唯一索引更大,但进一步阅读表明命中可以忽略不计

标签: sql-server indexing


【解决方案1】:

对于您的问题:

“这些连接通常是针对特定的 VersionID 完成的,所以这是最具选择性的列,应该是索引中的第一个。”

连接与它无关,除非连接被用作过滤器。 过滤器(Where 子句谓词)和排序(Order By 子句)使用索引。是否使用索引取决于有多少记录(行)满足过滤器。如果查询将返回表中的每一行(没有 where 子句),那么很可能不会使用索引,因为查询优化器会(正确地)决定它可能只读取整个表而不是尝试使用一个索引。索引是分层的树结构,具有多个级别。对于查询将返回的每一行,使用索引需要每个索引级别一个磁盘 I/O。因此,如果查询将返回表中的所有 1000 行,并且索引中有五个级别,那么这将需要 5000 次 IO。直接从表而不是索引中读取数据只需要 1000 次 IO。

接下来,您关于“这应该减轻对插入的性能影响的陈述,因为插入的行是一个可以添加到索引末尾的'块'”

仅当索引是聚集索引时,此语句才成立。在您的架构中,聚集索引是主键(因为虽然您可以覆盖它,但这是默认行为),它位于 ValuationID,而不是 VersionId。所以 any 记录的“块”的插入,无论它们是否都具有相同的 versionId,都将被添加到索引的末尾,因为它们都会有新的valuationIds。

【讨论】:

  • 好的,谢谢 - 重新加入是有道理的。我做了一个连接,然后在 where 子句中有 versionID,所以优化器会弄清楚使用 Valuation 上的索引,因为它是按 versionid 排序的,然后还在它连接到的表上使用类似的索引。
【解决方案2】:

是的,你说的都对。

应根据您查询较多的列对列进行排序,前列是您经常或最常查询的列。

添加具有递增值VersionID 的行意味着不需要拆分中间页面。

【讨论】:

    猜你喜欢
    • 2010-11-30
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    • 2012-11-16
    • 1970-01-01
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多