116

作为“什么是索引以及如何使用它们来优化我的数据库中的查询? ”的后续行动,我正在尝试了解索引,哪些列是好的索引候选?专门针对 MS SQL 数据库?

经过一番谷歌搜索后,我读到的所有内容都表明,通常会增加且唯一的列是一个很好的索引(比如 MySQL 的 auto_increment 之类的东西),我理解这一点,但我使用的是 MS SQL,并且我使用的是 GUID 作为主键,所以看起来索引不会使 GUID 列受益...

4

12 回答 12

135

索引可以在查询优化和从表中快速搜索结果中发挥重要作用。所以选择要索引的列是最重要的一步。有两个主要的地方我们可以考虑索引:WHERE 子句中引用的列和 JOIN 子句中使用的列。简而言之,应该为这些列建立索引,您需要根据这些列搜索特定记录。假设我们有一个名为 Buyer 的表,其中 SELECT 查询使用如下索引:

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 不会使用它来限制所选行。因此,没有必要对其进行索引。下面是另一个与上面略有不同的示例:

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,last_name 列可以被索引,因为它们位于 WHERE 子句中。还可以考虑将来自国家/地区表的附加字段 country_id 用于索引,因为它位于 JOIN 子句中。因此可以考虑对 WHERE 子句或 JOIN 子句中的每个字段进行索引。

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

  • 仅索引 WHERE 和 ORDER BY 子句中需要的那些列。大量索引列会导致一些缺点。
  • 尝试利用 MySQL 的“索引前缀”或“多列索引”功能。如果您创建索引,例如 INDEX(first_name, last_name),请不要创建 INDEX(first_name)。但是,并非所有搜索情况都建议使用“索引前缀”或“多列索引”。
  • 对您考虑索引的列使用 NOT NULL 属性,以便永远不会存储 NULL 值。
  • 使用 --log-long-format 选项记录不使用索引的查询。通过这种方式,您可以检查此日志文件并相应地调整您的查询。
  • EXPLAIN 语句帮助您揭示 MySQL 将如何执行查询。它显示了表的连接方式和顺序。这对于确定如何编写优化查询以及是否需要对列进行索引非常有用。

更新(2015 年 2 月 23 日):

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

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

很可能在任何一本书中,“索引页”都可能有章节起始页、主题页码起始页以及子主题页起始页。索引页面中的一些说明会有所帮助,但更详细的索引可能会使您感到困惑或吓到您。索引也有记忆。

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

于 2012-01-20T07:03:40.093 回答
23

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

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

还要考虑你创建的索引类型——B-trees 适用于大多数事情并允许范围查询,但哈希索引让你直截了当(但不允许范围)。其他类型的索引也有其他优点和缺点。

祝你好运!

于 2008-09-20T04:55:00.270 回答
13

这完全取决于您希望对表提出什么查询。如果您要求 X 列具有特定值的所有行,则如果无法使用索引,则必须进行全表扫描。

在以下情况下,索引将很有用:

  • 列或列具有高度的唯一性
  • 您经常需要为列查找某个值或值范围。

如果出现以下情况,它们将无用:

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

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

于 2008-09-20T05:01:03.530 回答
7

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

这包括:外键 -

select * from tblOrder where status_id=:v_outstanding

描述性字段 -

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

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

select * from tblOrder where paidYN='N'
于 2008-09-20T05:03:17.957 回答
5

一般来说(我不使用 mssql,所以不能具体评论),主键是很好的索引。它们是唯一的,并且必须具有指定的值。(此外,主键生成的索引非常好,以至于它们通常会自动创建一个索引。)

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

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

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

于 2008-09-20T04:49:50.467 回答
3

GUID 列不是索引的最佳候选者。索引最适合数据类型的列,该数据类型可以给出一些有意义的顺序,即排序(整数、日期等)。

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

还可以创建一个“聚集索引”,对您的数据进行物理重新排序。但是,每个表只能有一个,而可以有多个非聚集索引。

于 2008-09-20T04:50:21.327 回答
3

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

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

于 2008-09-20T04:50:39.267 回答
2

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

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

于 2008-09-20T05:00:34.593 回答
2

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

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

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

于 2008-09-20T05:18:08.137 回答
1

经验法则是在 WHERE、ORDER BY 和 GROUP BY 子句中经常使用的列,或者在连接中经常使用的任何列。请记住,我指的是索引,而不是主键

不要给出一个“香草味”的答案,但这真的取决于你如何访问数据

于 2008-09-20T04:56:15.243 回答
0

如果您使用 GUID,它应该会更快。假设你有记录

  1. 100
  2. 200
  3. 3000
  4. ……

如果你有索引(二分查找,你可以在 O(lg n) 时间内找到你要查找的记录的物理位置,而不是按顺序查找 O(n) 时间。这是因为你不知道你有哪些记录在你的桌子上。

于 2008-09-20T04:50:24.633 回答
0

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

举个例子 一个成员数据库,其主键是成员社会保障号。我们选择 SS 是因为应用程序主要以这种方式引用个人,但您还想创建一个搜索功能,该功能将利用成员的名字和姓氏。然后我建议在这两个字段上创建一个索引。

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

于 2008-09-20T04:59:13.130 回答