sql-server - 帮助了解索引上的多个列?

标签 sql-server tsql indexing

假设我有一个名为“表”的表,并且我有3列,a,b和c。

在a,b列上具有非聚集索引是什么意思?

a,b列上的非聚集索引是否与b,a列上的非聚集索引相同? (请注意顺序)。

另外,列a上的非聚集索引是否与a,c上的非聚集索引相同?

我正在查看网站sqlserver的性能,他们使用了这些dmv脚本,它们会在其中告诉您索引是否重叠,并且我相信这是在说a上的索引与a,b相同,所以这是多余的。索引是否正确?

最后一个问题是为什么将聚簇索引放在主键上。大多数情况下,不查询主键,因此聚集索引不应位于查询最多的列上。我可能在这里缺少某些东西,例如将其放在主键上可以加快联接速度?

很好的解释。我应该将其转变为Wiki并更改标题索引说明吗?

最佳答案

这将成为索引的更一般性介绍,但我怀疑您仍然会发现它很有用。前两段特别谈到您的问题。
集群与非集群
这指的是表在磁盘上的物理排列方式。聚集索引通过根据索引定义对磁盘上表中的物理页和行进行排序来工作。非聚集索引使用磁盘上的单独位置在索引中存储列的副本(并且仅存储那些列),以及指向源记录的指针。因此,聚集索引通常更快,因为它们将始终覆盖查询中所需的任何数据。但是,您只能获得其中之一,因为否则您将复制整个表。同样重要的是要知道,将非聚集索引添加到表中实际上会减慢诸如插入和更新之类的写操作,因为数据库必须重建索引或至少索引中的某些页面。
索引顺序(A,B)上的索引与(B,A)上的索引不同。如果是第一种情况,则索引中的记录首先按A列进行排序,而B列仅在A具有重复值时才影响索引顺序。仅使用B列值搜索索引无济于事,因为您仍然需要浏览索引中的每条记录以找到B中所有匹配的值。在第二种情况下,情况恰好相反:记录首先按B列进行排序,而A列仅在您具有A的重复值时才有用。仅使用A列值搜索该索引将无济于事。
覆盖指数
有时数据库可以完全通过索引满足查询的要求。在这种情况下,该索引被称为该查询的“覆盖”索引。这是有利的,因为索引通常被缓存在内存中,因此数据库可能根本不需要做磁盘。要理解这一点,请想象(A,B)上的索引,其中A的重复值很少。除非在查询中经常运行查找A的特定值并且还需要A的索引,否则在索引中包括B似乎很浪费。现在,此索引将节省很多工作,可返回到原始表以检索B
选择性
选择性是一个介于0到1之间的值(通常表示为百分比),它告诉您索引中每个值的唯一性。选择性为1或100%表示没有重复项。选择性为0表示该列中只有一个值。通常,对于索引,较高的选择性(接近1)更好。
为了证明这一点,请考虑使用低选择性指数会发生什么。例如,您尝试通过向具有10000条记录的表中的bit列添加索引来加快查询速度。在这种情况下(假设分布均匀),选择性为0.5。您运行查询,索引返回5000条记录。但是这些记录中的每条记录仍必须返回到原始表,并且由于索引顺序与表顺序不匹配,因此必须对表进行大量单独的查找。相反,仅扫描整个表开始到完成以检索所需的数据可能会更快。
选择性说明了为什么要在主键上进行聚类。由于聚簇索引告诉数据库如何对表进行排序,因此,如果选择性低于100%,则意味着查询将不得不更频繁地扫描表。主键上的聚类为您提供了完美的选择性。并且由于该主键通常用作其他索引中的记录指针,因此您希望使其尽可能小(即,整数标识列)。
这里有一篇关于选择性和索引的好文章:
http://www.akadia.com/services/ora_index_selectivity.html
可燃的
这是指数据库是否能够使用带有索引的特定过滤器。
如我们所展示的,索引通常通过首先按特定顺序对数据进行排序来工作,因此对索引的查找可以使用诸如基于树的搜索之类的高效方法,而不是较慢的线性搜索。任何无法与已排序数据进行有效比较的内容都不能与索引一起使用。一个很好的例子是LIKE运算符。这是可确定的:

SELECT * FROM [Table] WHERE [Column] LIKE @Value + '%'
但这不是可靠的:
SELECT * FROM [Table] WHERE [Column] LIKE '%' + @Value + '%'
其他一些可能使过滤器不可靠的事情是不确定性函数(其中有很多比您想象的要多)。
每列索引
我看到的一个常见错误是表中的每一列都有一个单独的索引。例如,某人将创建一个包含(A,B,C,D)列的表,并创建四个单独的索引,每个索引分别用于ABCD,以为他们现在已经索引了每一列,因此每个查询都应该是快速的。实际上,由于我希望已经解释的原因,这很少有用,并且通常会使情况变得更糟而不是更好,因为数据库现在需要针对数据的每次更改更新这些索引。

关于sql-server - 帮助了解索引上的多个列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1434148/

相关文章:

javascript - 如何在不刷新页面的情况下从php中的sql server数据库中获取数据

sql - 如何使用 unpivot 函数在其他列中查找最小值来忽略字符串值

sql - TSQL 连接查询

jquery .each 仅适用于第一个元素

javascript - 找出 Javascript 中给定数字中的哪一个与其他数字不同

postgresql - 通过在 postgresql 上索引时间戳列来加快搜索速度?

python - 在 docker 镜像中安装 pyodbc

sql-server - 有什么方法可以让我从现有的数据库生成 SQL 脚本吗?

tsql - T-SQL - 交叉应用到 PIVOT? (将数据透视表与表值函数一起使用)?

要以逗号分隔的形式转换的 sql server 列值