关于sql server:哪些列通常会成为好的索引?

What columns generally make good indexes?

作为"什么是索引以及如何使用它们优化数据库中的查询"的后续操作?在我试图了解索引的地方,哪些列是好的索引候选列?专门针对MS SQL数据库?

在谷歌搜索之后,我读到的每一篇文章都表明,通常递增且唯一的列是一个很好的索引(比如mysql的auto_increment),我理解这一点,但我使用的是ms-sql,而我使用的是guid作为主键,所以索引似乎对guid列没有好处……


索引可以在查询优化和从表中快速搜索结果方面发挥重要作用。因此,选择要索引的列是最重要的步骤。我们可以在两个主要位置考虑索引:WHERE子句中引用的列和JOIN子句中使用的列。简而言之,这样的列应该被索引,您需要根据它来搜索特定的记录。假设我们有一个名为buyers的表,其中select查询使用如下索引:

1
2
3
4
5
SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

因为在select部分引用了"buyer-id",所以mysql不会使用它来限制所选的行。因此,无需对其进行索引。下面是另一个与上面的例子稍有不同的例子:

1
2
3
4
5
6
7
8
9
SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

根据上面的查询first_name,可以索引姓氏列,因为它们位于where子句中。另外一个字段country_id from country table也可以考虑索引,因为它在join子句中。因此,可以在WHERE子句或JOIN子句的每个字段上考虑索引。

下面的列表还提供了一些提示,当您打算在表中创建索引时,应该始终记住这些提示:

  • 仅对WHERE和ORDER BY子句中所需的列进行索引。大量索引列会导致一些缺点。
  • 尽量利用MySQL的"索引前缀"或"多列索引"功能。如果您创建一个索引,比如索引(名字、姓氏),不要创建索引(名字)。但是,不建议在所有搜索案例中使用"索引前缀"或"多列索引"。
  • 对考虑索引的列使用非空属性,这样就永远不会存储空值。
  • 使用--log long format选项记录不使用索引的查询。通过这种方式,您可以检查这个日志文件并相应地调整查询。
  • explain语句帮助您揭示MySQL将如何执行查询。它显示了表的联接方式和顺序。这对于确定如何编写优化的查询以及是否需要为列编制索引非常有用。

更新(2015年2月23日):

任何索引(好/坏)都会增加插入和更新时间。

根据您的索引(索引数量和类型),搜索结果。如果你的搜索时间因为索引而增加,那就是坏索引。

很可能在任何一本书中,"索引页"都会有章节开始页、主题页码开始,也会有子主题页开始。索引页中的一些说明有帮助,但更详细的索引可能会使您困惑或感到害怕。索引也有内存。

索引选择应该是明智的。请记住,并非所有列都需要索引。


有些人回答了类似的问题:你怎么知道什么是好的索引?

基本上,这取决于您将如何查询数据。您需要一个索引来快速标识与查询相关的数据集的一小部分。如果从不按日期戳查询,则不需要索引,即使它大部分是唯一的。如果你所做的只是得到某个日期范围内发生的事件,你肯定想要一个。在大多数情况下,一个关于性别的索引是没有意义的——但是如果你所做的只是获得关于所有男性的统计数据,并且分别获得关于所有女性的统计数据,那么创建一个这样的索引可能是值得的。弄清楚您的查询模式是什么,访问哪个参数会最大程度地缩小搜索空间,这是您最好的索引。

还要考虑您所做的索引的类型——B-树对大多数事情都很好,并且允许范围查询,但是哈希索引可以让您直接到达目的地(但不允许范围)。其他类型的指数还有其他的利弊。

祝你好运!


这完全取决于您希望询问关于表的哪些查询。如果您为X列请求具有特定值的所有行,则如果无法使用索引,则必须进行完整的表扫描。

如果出现以下情况,索引将很有用:

  • 列具有高度的唯一性
  • 您经常需要查找列。

如果出现以下情况,它们将不起作用:

  • 您正在选择表中较大百分比(>10-20%)的行
  • 额外的空间使用是一个问题
  • 您希望最大限度地提高插入性能。表中的每个索引都会降低插入和更新性能,因为每次数据更改时都必须更新它们。

主键列通常非常适合索引,因为它们是唯一的,并且经常用于查找行。


一般来说(我不使用mssql,所以不能特别评论),主键是很好的索引。它们是唯一的,必须指定一个值。(而且,主键的索引非常好,通常会自动创建索引。)

索引实际上是一个列的副本,该列已被排序为允许二进制搜索(比线性搜索快得多)。数据库系统可能会使用各种技巧来加快搜索速度,尤其是在数据比简单数字更复杂的情况下。

我的建议是最初不要使用任何索引并分析您的查询。如果经常运行特定的查询(例如,按姓氏搜索人员),请尝试在重新激活的属性和配置文件上创建索引。如果查询速度明显加快,插入和更新速度可以忽略不计,请保留索引。

(抱歉,如果我在重复你另一个问题中提到的内容,我以前没有遇到过。)


任何将定期用于从表中提取数据的列都应该被索引。

这包括:外键-

1
select * from tblOrder where status_id=:v_outstanding

描述性字段-

1
select * from tblCust where Surname like"O'Brian%"

列不需要是唯一的。事实上,在搜索异常时,可以从二进制索引中获得非常好的性能。

1
select * from tblOrder where paidYN='N'


这取决于你的询问。例如,如果您几乎只写一个表,那么最好不要有任何索引,它们只会减慢写入速度,永远不会被使用。用于与另一个表联接的任何列都是索引的好候选列。

另外,请阅读"缺少索引"功能。它监视对数据库使用的实际查询,并可以告诉您哪些索引可以提高性能。


guid列不是索引的最佳候选列。索引最适合具有数据类型的列,这些数据类型可以指定一些有意义的顺序,例如排序(整数、日期等)。

列中的数据是否通常在增加并不重要。如果在列上创建索引,则索引将创建自己的数据结构,该数据结构只引用表中的实际项,而不考虑存储顺序(非聚集索引)。例如,可以在索引数据结构上执行二进制搜索,以提供快速检索。

也可以创建一个"聚集索引",它将对数据进行物理重新排序。但是,每个表只能有一个这样的索引,而可以有多个非聚集索引。


按升序或降序排列的数字数据类型由于多种原因是很好的索引。首先,数字的计算速度通常比字符串(varchar、char、nvarchar等)快。其次,如果您的值没有排序,那么可能需要对行和/或页进行无序排列以更新索引。这是额外的开销。

如果您使用的是SQL Server 2005并设置为使用uniqueidentifier(guid),并且不需要它们是随机的,请检查顺序uniqueidentifier类型。

最后,如果您谈论的是聚集索引,那么您谈论的是物理数据的种类。如果您有一个字符串作为聚集索引,那可能会变得很难看。


您的主键应该始终是索引。(事实上,如果不是由MS SQL自动索引的话,我会感到惊讶。)您还应该经常索引您的SELECTORDER列;它们的目的是快速查找单个值和快速排序。

索引too许多列的唯一真正危险是减慢对大表中行的更改,因为索引也都需要更新。如果您真的不确定要索引什么,只需为最慢的查询计时,查看最常用的列,并对它们进行索引。然后看看他们有多快。


最佳索引取决于表的内容和您要完成的任务。

以一个成员数据库为例,该数据库具有成员社会保障编号的主键。我们选择S.S.是因为应用程序priamry以这种方式引用个人,但您也希望创建一个搜索函数,该函数将使用成员的名字和姓氏。然后我建议在这两个字段上创建索引。

您应该首先找出要查询的数据,然后确定需要索引哪些数据。


ol的经验法则是在where、order by和group by子句中经常使用的列,或者在join中经常使用的任何列。记住,我指的是索引,不是主键

不是给出一个"普通"的答案,而是真正取决于您如何访问数据。


如果您使用的是guid,它应该更快。假设你有记录

  • 一百
  • 二百
  • 三千
  • 如果您有一个索引(二进制搜索),那么您可以在O(lg n)时间内找到要查找的记录的物理位置,而不是按顺序搜索O(n)时间。这是因为你不知道你桌上有什么记录。