索引中列的顺序有多重要?

时间:2010-02-18 22:18:51

标签: sql sql-server sql-server-2005 tsql indexing

我听说你应该在索引声明的开头放置最具选择性的列。例如:

CREATE NONCLUSTERED INDEX MyINDX on Table1
(
   MostSelective,
   SecondMost,
   Least
)

首先,我说的是对的吗?如果是这样,我可能会通过重新排列索引中列的顺序看到性能上的巨大差异,还是更多的是“很好做”的做法?

我问的原因是因为在通过DTA进行查询之后,它建议我创建一个索引,其中几乎所有列都与现有索引相同,只是顺序不同。我正在考虑将缺少的列添加到现有索引并将其称为好。想法?

5 个答案:

答案 0 :(得分:175)

查看这样的索引:

Cols
  1   2   3
-------------
|   | 1 |   |
| A |---|   |
|   | 2 |   |
|---|---|   |
|   |   |   |
|   | 1 | 9 |
| B |   |   |
|   |---|   |
|   | 2 |   |
|   |---|   |
|   | 3 |   |
|---|---|   |

首先了解对A的限制,因为您的第一列消除了比首先限制第二列更多的结果?如果您想象索引必须如何遍历第1列,然后是第2列等,则会更容易...您会看到在第一次通过中删除大部分结果会使第2步更快。

另一种情况,如果您在第3列上查询,优化器甚至不会使用索引,因为它在缩小结果集方面没有任何帮助。 只要您在查询中,在下一步之前缩小要处理的结果数量就意味着更好的效果。

由于索引也以这种方式存储,因此当您查询索引时,索引中没有回溯以查找第一列。

简而言之:不,它不是为了表演,有真正的性能优势。

答案 1 :(得分:113)

列的顺序至关重要。现在哪个订单是正确的,这取决于您将如何查询它。索引可用于执行精确搜索或范围扫描。精确搜索是指定索引中所有列的值并且查询准确归属于行感兴趣的内容。对于搜索,列的顺序无关紧要。范围扫描是指定只有一些列,在这种情况下,当订单变得重要时。仅当指定了最左侧的列时,SQL Server才能使用索引进行范围扫描,然后仅在指定了下一个最左侧的列时才使用索引,依此类推。如果您有(A,B,C)的索引,则可以使用A=@a的扫描范围,A=@a AND B=@b扫描B=@b但<{1}}的范围C=@cB=@b AND C=@c。案例A=@a AND C=@c是混合的,因为A=@a部分将使用索引,但C=@c不是(查询将扫描A=@a的所有B值,不会'跳过'到C=@c)。其他数据库系统具有所谓的“跳过扫描”运算符,当未指定外部列时,它可以利用索引中的内部列。

掌握了这些知识后,您可以再次查看索引定义。 (MostSelective, SecondMost, Least)上的索引仅在指定MostSelective列时才有效。但这是最具选择性的,内部列的相关性将迅速降低。通常,您会发现(MostSelective) include (SecondMost, Least)(MostSelective, SecondMost) include (Least)上有更好的索引。因为内部列不太相关,所以在索引中的这些正确位置放置低选择性列使得它们只是搜索的噪声,因此将它们移出中间页面并将它们仅保留在叶页上是有意义的,因为查询可覆盖性目的。换句话说,将它们移动到INCLUDE。随着Least列的大小增加,这变得更加重要。我们的想法是,此索引只能将指定MostSelective的查询作为精确值或范围受益,并且该列选择性最强,它已经在很大程度上限制了候选行。

另一方面,(Least, SecondMost, MostSelective)上的索引可能看似错误,但实际上它是一个非常强大的索引。因为它具有Least列作为其最外层查询,所以它可用于必须在低选择性列上聚合结果的查询。此类查询在OLAP和分析数据仓库中很普遍,而这正是这些索引具有非常好的案例的地方。这些索引实际上构成了优秀的聚簇索引,正是因为它们组织了大块相关行的物理布局(相同的Least值,这通常表示某种类别或类型)并且它们便于实现分析查询。

所以,不幸的是,没有'正确'的顺序。您不应该遵循任何cookie切割器配方,而是分析您将要对这些表使用的查询模式,并确定哪个索引列顺序正确。

答案 2 :(得分:37)

正如雷木思所说,这取决于你的工作量。

我想解决接受的答案的误导性方面。

对于在索引中的所有列上执行相等搜索的查询,没有显着差异。

下面创建两个表并用相同的数据填充它们。唯一的区别是,一个人的按键排序从大多数到最少的选择,另一个反过来。

CREATE TABLE Table1(MostSelective char(800), SecondMost TINYINT, Least  CHAR(1), Filler CHAR(4000) null);
CREATE TABLE Table2(MostSelective char(800), SecondMost TINYINT, Least  CHAR(1), Filler CHAR(4000) null);

CREATE NONCLUSTERED INDEX MyINDX on Table1(MostSelective,SecondMost,Least);
CREATE NONCLUSTERED INDEX MyINDX2 on Table2(Least,SecondMost,MostSelective);

INSERT INTO Table1 (MostSelective, SecondMost, Least)
output inserted.* into Table2
SELECT TOP 26 REPLICATE(CHAR(number + 65),800), number/5, '~'
FROM master..spt_values
WHERE type = 'P' AND number >= 0
ORDER BY number;

现在对两个表进行查询......

SELECT *
FROM   Table1
WHERE  MostSelective = REPLICATE('P', 800)
       AND SecondMost = 3
       AND Least = '~';

SELECT *
FROM   Table2
WHERE  MostSelective = REPLICATE('P', 800)
       AND SecondMost = 3
       AND Least = '~'; 

......他们两个都使用索引罚款,两者的成本完全相同。

enter image description here

接受答案中的ASCII艺术实际上并不是索引的结构。 Table1的索引页面如下所示(单击图像以完整大小打开)。

enter image description here

索引页面包含包含整个键的行(在这种情况下,实际上为行标识符附加了一个附加键列,因为索引未声明为唯一但可以忽略further information about this can be found here)。

对于上面的查询,SQL Server不关心列的选择性。它对根页进行二进制搜索,发现 (PPP...,3,~ )>=(JJJ...,1,~ )< (SSS...,3,~ ),因此它应该读取页面1:118。然后,它对该页面上的键条目进行二进制搜索,并定位叶子页面以向下移动。

按选择性顺序更改索引不会影响二进制搜索的预期密钥比较次数或需要导航以执行索引查找的页面数。最好可能略微加快密钥比较本身。

有时,首先订购最具选择性的索引对于您的工作负载中的其他查询也是有意义的。

例如,如果工作负载包含以下两种形式的查询。

SELECT * ... WHERE  MostSelective = 'P'

SELECT * ...WHERE Least = '~'

上述指数并未涵盖其中任何一项。 MostSelective具有足够的选择性,可以制定一个值得查找和查找的计划,但针对Least的查询却不是。

然而,这种情况(非覆盖索引寻找复合索引的前导列的子集)只是一个可以由索引帮助的可能的查询类。如果您实际上从未实际按MostSelectiveMostSelective, SecondMost的组合进行搜索,并且总是通过所有三列的组合搜索,那么这种理论优势对您来说毫无用处。

相反查询,例如

SELECT MostSelective,
       SecondMost,
       Least
FROM   Table2
WHERE  Least = '~'
ORDER  BY SecondMost,
          MostSelective 

通过使用通常规定的相反顺序(因为它涵盖了查询),可以支持搜索并以所需顺序返回行以启动。

所以这是一个经常重复的建议,但最多它是关于其他查询的潜在好处的启发式方法 - 并且它无法替代实际查看您的工作量。

答案 3 :(得分:30)

  

你应该在索引声明的开头放置最具选择性的列。

正确。 索引可以是复合 - 由多列组成 - 由于最左边的原则,顺序很重要。原因是,数据库从左到右检查列表,并且必须找到与定义的顺序匹配的相应列引用。例如,在地址表上包含索引的索引:

  • 地址
  • 国家

使用address列的任何查询都可以使用索引,但如果查询只有city和/或state引用,则无法使用索引。这是因为没有引用最左边的列。查询性能应该告诉您哪个是最优的 - 单个索引,或具有不同订单的多个组合。好读:The Tipping Point,作者:Kimberley Tripp

答案 4 :(得分:2)

所有答案都是错误的。

选择索引时,综合索引中各个列的选择性 无关紧要。

简单的思考过程如下:有效地,索引是所涉及列的串联。

基于这种原理,唯一的区别是比较字符串中前后不同的两个“字符串”。这只是总成本的一小部分。如一个答案中所述,没有“第一遍/第二遍”。

那么,应该使用什么顺序?

  1. 从<{> 1 ”顺序开始,以// Your collection Array var collectionArray = [] // make change event on chosen select field chosenSelect.change(function () { // first get the chosen results which might be in wrong order var currentValues = $(this).val(); // get your current collection that is in the right order var pastValues = collectionArray; // see if you need to add or drop if (currentValues.length > pastValue.length) { // loop to get just the new item pastValues.forEach(function(pastValue) { currentValue = $.grep(currentValue, function(newItemOnly) { return newItemOnly != pastValue; }); }); // add your newItemOnly collectionArray.push(currentValue[0]); } else { // here loop to get only the dropped value currentValues.forEach(function(currentValue) { pastValues = $.grep(pastValues, function(droppedValueOnly) { return droppedValueOnly != currentValue; }); }); // drop the value dropped from your collection collectionArray = $.grep(collectionArray, function(updatedArray) { return updatedArray != pastValues[0]; }); } }); 测试的列开始。
  2. 然后在一个范围列上固定。

例如,选择性很低的列必须排在最前面:

library(plotly)
library(shiny)

ui <- fluidPage(
  plotlyOutput("plot"),
  verbatimTextOutput("event")
)
server <- function(input, output, session) {

  #df sample using dput
  df <- structure(list(col_group = structure(1:8, .Label = c("1", "2", 
                                                             "3", "4", "5", "6", "7", "8"), class = "factor"), color = structure(c(4L, 
                                                                                                                                   6L, 7L, 8L, 5L, 3L, 2L, 1L), .Label = c("#1A9850", "#66BD63", 
                                                                                                                                                                           "#A6D96A", "#D73027", "#D9EF8B", "#F46D43", "#FDAE61", "#FEE08B"
                                                                                                                                   ), class = "factor"), geometry = structure(list(structure(c(4.52343199617246, 
                                                                                                                                                                                               4.52324233358547, 4.52267342343957, 4.52224662532908, 4.52210428346744, 
                                                                                                                                                                                               4.52200925015845, 4.52192088448668, 4.52180475361204, 4.52172945325391, 
                                                                                                                                                                                               4.52168196905882, 4.5215535740952, 4.52095980475523, 4.52076420632298, 
                                                                                                                                                                                               4.52062274547478, 51.9453195440486, 51.9453722803981, 51.945526317454, 
                                                                                                                                                                                               51.9456480852256, 51.9456928353329, 51.9457296098645, 51.9457705951341, 
                                                                                                                                                                                               51.9458530114811, 51.945914910501, 51.9459312169901, 51.9459510896027, 
                                                                                                                                                                                               51.9459966849614, 51.9460077291392, 51.9460066867221), .Dim = c(14L, 
                                                                                                                                                                                                                                                               2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.4964540696277, 
                                                                                                                                                                                                                                                                                                                       4.49696710232736, 51.9086692611627, 51.9084484303039), .Dim = c(2L, 
                                                                                                                                                                                                                                                                                                                                                                                       2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.13635479859532, 
                                                                                                                                                                                                                                                                                                                                                                                                                                               4.13644010080625, 51.975098751212, 51.9751715711302), .Dim = c(2L, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.47801457239531, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      4.47834576882542, 51.9300740588744, 51.9304218318716), .Dim = c(2L, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.45974369011875, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              4.46029492493512, 4.46033964902157, 51.9290774018138, 51.9284345596986, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              51.9283809798498), .Dim = 3:2, class = c("XY", "LINESTRING", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "sfg")), structure(c(4.43886518844695, 4.43891013390463, 4.43910559159559, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            4.43913561800293, 51.93455577157, 51.9344932127658, 51.9341891712133, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            51.9341444695365), .Dim = c(4L, 2L), class = c("XY", "LINESTRING", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "sfg")), structure(c(4.54844667292407, 4.55002805772657, 51.9658870347267, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                51.9661409927825), .Dim = c(2L, 2L), class = c("XY", "LINESTRING", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "sfg")), structure(c(4.47522875290306, 4.47598748813623, 51.9347985281278, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    51.9353886781931), .Dim = c(2L, 2L), class = c("XY", "LINESTRING", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "sfg"))), class = c("sfc_LINESTRING", "sfc"), precision = 0, bbox = structure(c(xmin = 4.13635479859532, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ymin = 51.9084484303039, xmax = 4.55002805772657, ymax = 51.9751715711302
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ), class = "bbox"), crs = structure(list(epsg = 4326L, proj4string = "+proj=longlat +datum=WGS84 +no_defs"), class = "crs"), n_empty = 0L), 
                       key = c("1", "8000", "10000", "12000", "14000", "16000", 
                               "18000", "22000")), row.names = c(1L, 8000L, 10000L, 12000L, 
                                                                 14000L, 16000L, 18000L, 22000L), class = c("sf", "data.frame"
                                                                 ), sf_column = "geometry", agr = structure(c(col_group = NA_integer_, 
                                                                                                              color = NA_integer_, key = NA_integer_), .Label = c("constant", 
                                                                                                                                                                  "aggregate", "identity"), class = "factor"))
  #plotly
  output$plot <- renderPlotly({
    plot_geo(df, type = "scattergl", mode = "lines",
             customdata = ~key,
             color = ~col_group, colors = rev(RColorBrewer::brewer.pal(8, name = "RdYlGn"))
    )
  })

  #event_data
  output$event <- renderPrint({
    d <- event_data("plotly_click")
    if (is.null(d)) "Click events appear here (double-click to clear)" else {
      df_select <- df[df$key %in% d$customdata,]
      print(df_select)
    }
  })

}
shinyApp(ui, server)

在索引中交换顺序会完全忽略=

(还有更多的列排序规则。)