Sql 非聚集覆盖索引列选择规则

Sql 非聚集覆盖索引列选择规则,sql,indexing,Sql,Indexing,我有一个大约有19列的表,其中包含相当大的数据量,主要是使用基于不同where子句的select语句来检索数据。由于查询此表主要是为了获取数据,因此我考虑根据查询中使用的不同where子句创建非聚集索引。此外,所有get查询都会返回表中的所有列,作为选择列表的一部分。基于上述信息,我有两个问题需要选择索引: 假设我们有以下SP,其查询如下: where [col_a] = {value} and [col_b] = {value} [col_b] = {value} and [co

我有一个大约有19列的表,其中包含相当大的数据量,主要是使用基于不同where子句的select语句来检索数据。由于查询此表主要是为了获取数据,因此我考虑根据查询中使用的不同where子句创建非聚集索引。此外,所有get查询都会返回表中的所有列,作为选择列表的一部分。基于上述信息,我有两个问题需要选择索引:

  • 假设我们有以下SP,其查询如下:

    where [col_a] = {value} and [col_b] = {value}
    
          [col_b] = {value} and [col_a] = {value}
    
          [col_a] = {value} and [col_c] = {value} and [col_d] = {value}
    
          [col_a] = {value} and [col_c] = {value}
    
    我在表上创建了以下非聚集索引,如下所示

    [col_a]和[col_b]-->第一个SP是否仍将此索引用作 命令颠倒了

    [col_a]和[col_c]和[col_d]-->最后一个SP会使用此索引吗 因为前两列与顺序匹配

    此外,我们是否应该继续并尝试根据表上get SP的filter/join子句定义非聚集索引

  • 由于所有SP中的select列表返回整个列列表,因此我将表中的所有列添加为非聚集索引(覆盖索引)中的包含列,以避免书签查找。这种方法正确吗?既然我们将所有表列存储为索引定义的一部分,那么这种情况下的空间含义是什么

  • [col_a]和[col_b]
    第一个SP是否仍将此索引用作 顺序颠倒了

    是-如果同时指定两列,并且索引包含这两列作为其列列表中的前两列,则可以使用索引,并且顺序并不重要

    如果您有一个索引
    (列a、列b)
    ,如果您指定以下内容,则可以使用该索引:

    • 只是
      col\u a
    • 列a
      列b
      (顺序无关)
    但是它不能用于只指定列b(而不是列a)的查询。为了考虑使用,必须以任意顺序使用/定义最左边的n列(n>=1)

    [col_a]和[col_c]和[col_d]
    最后一个SP会使用此索引吗 因为前两列与顺序匹配

    是的-正如我上面提到的,如果使用最左边的n列,可以考虑索引,因此如果您指定总共三列中的前两列,您就可以了


    警告:仅仅因为您指定了正确的列,并不一定意味着最终将实际使用索引。查询优化器会考虑使用它,但是如果这更方便/更快,它可能会以另一种方式运行。

    这里WHERE子句中的排序与此无关。因此,是的,这两个索引将很好地服务于所有四个示例

    至于帮助加入的索引,是的,一般都建议使用

    您可能会发现,如果您创建的索引非常适合您曾经使用的每个连接,那么您就有了很多索引。这可能导致写入表时出现性能问题。在这种情况下,您可能会发现一小部分索引对于连接和WHERE子句来说并不完美,但它们足够好,您只需使用这几部分即可。这是一种妥协,你需要平衡自己


    最后,请注意一些RDBMS可以使用索引合并。这可能意味着多个简单或更简单的索引几乎与复合/覆盖索引一样好。但在大多数情况下,在考虑索引时,您需要同时考虑WHERE子句和连接。 这是因为索引的主要特征是记录的顺序。理想的情况是将所有感兴趣的记录都放在一个顺序块中(在WHERE子句和联接过滤掉它之后),并且顺序对后续联接或GROUP BY有利。实际上,您的目标是使数据位于尽可能少的顺序集群中,并且尽可能符合顺序。然后让RDBMS优化人员完成剩下的工作:)