作为我试图了解索引的“What are indexes and how can I use them to optimise queries in my database?”的后续,哪些列是好的索引候选?专门针对 MS SQL 数据库?
经过一番谷歌搜索后,我读到的所有内容都表明,通常增加且唯一的列是一个很好的索引(比如 MySQL 的 auto_increment 之类的东西),我理解这一点,但我使用的是 MS SQL,并且我使用的是 GUID 作为主键,所以看起来索引不会使 GUID 列受益...
索引可以在查询优化和从表中快速搜索结果中发挥重要作用。最重要的一步是选择要索引的列。有两个主要的地方我们可以考虑索引:WHERE 子句中引用的列和 JOIN 子句中使用的列。简而言之,应该为这些列建立索引,您需要根据这些列搜索特定记录。假设我们有一个名为 Buyer 的表,其中 SELECT 查询使用如下索引:
SELECT
buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider indexing */
AND last_name='Iqbal' /* consider indexing */
由于 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 indexing */
WHERE
first_name='Tariq' /* consider indexing */
AND
last_name='Iqbal' /* consider indexing */
根据上面的查询 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 日):
任何索引(好/坏)都会增加插入和更新时间。
根据您的索引(索引数量和类型),搜索结果。如果您的搜索时间会因为索引而增加,那么这就是糟糕的索引。
很可能在任何一本书中,“索引页”都可能有章节起始页、主题页码起始页以及子主题页起始页。索引页面中的一些说明会有所帮助,但更详细的索引可能会使您感到困惑或吓到您。索引也有记忆。
索引选择应该是明智的。请记住,并非所有列都需要索引。
有些人在这里回答了类似的问题:How do you know what a good index is?
基本上,这实际上取决于您将如何查询数据。您需要一个能够快速识别与查询相关的一小部分数据集的索引。如果您从不按日期戳查询,则不需要索引,即使它大多是唯一的。如果您所做的只是获取某个日期范围内发生的事件,那么您肯定想要一个。在大多数情况下,关于性别的索引是没有意义的——但如果你所做的只是获取所有男性的统计数据,并且单独获取所有女性的统计数据,那么创建一个索引可能是值得的。弄清楚您的查询模式将是什么,并访问哪个参数最能缩小搜索空间,这就是您的最佳索引。
还要考虑你创建的索引类型——B-trees 适用于大多数事情并允许范围查询,但哈希索引让你直截了当(但不允许范围)。其他类型的索引也有其他优点和缺点。
祝你好运!
这完全取决于您希望对表提出什么查询。如果您要求 X 列具有特定值的所有行,如果无法使用索引,则必须进行全表扫描。
在以下情况下,索引将很有用:
列或列具有高度的唯一性
您经常需要为列查找某个值或值范围。
如果出现以下情况,它们将无用:
您正在选择表中较大的 % (>10-20%) 行
额外的空间使用是一个问题
您希望最大限度地提高插入性能。表上的每个索引都会降低插入和更新性能,因为每次数据更改时都必须更新它们。
主键列通常非常适合索引,因为它们是唯一的并且通常用于查找行。
任何将经常用于从表中提取数据的列都应该被索引。
这包括:外键 -
select * from tblOrder where status_id=:v_outstanding
描述性字段 -
select * from tblCust where Surname like "O'Brian%"
列不需要是唯一的。事实上,在搜索异常时,您可以从二进制索引中获得非常好的性能。
select * from tblOrder where paidYN='N'
一般来说(我不使用 mssql,所以不能具体评论),主键是很好的索引。它们是唯一的,并且必须具有指定的值。 (此外,主键生成的索引非常好,以至于它们通常会自动创建一个索引。)
索引实际上是已排序以允许二进制搜索(比线性搜索快得多)的列的副本。数据库系统可能会使用各种技巧来进一步加快搜索速度,尤其是在数据比简单数字更复杂的情况下。
我的建议是最初不要使用任何索引并分析您的查询。如果某个特定查询(例如按姓氏搜索人员)运行频率很高,请尝试再次在相关属性和配置文件上创建索引。如果查询的速度明显加快,而插入和更新的速度可以忽略不计,请保留索引。
(抱歉,如果我重复您在另一个问题中提到的内容,我之前没有遇到过。)
这实际上取决于您的查询。例如,如果您几乎只写入表,那么最好不要有任何索引,它们只会减慢写入速度并且永远不会被使用。您用于与另一个表连接的任何列都是索引的良好候选者。
此外,请阅读有关缺失索引功能的信息。它监视对您的数据库使用的实际查询,并可以告诉您哪些索引可以提高性能。
GUID 列不是索引的最佳候选者。索引最适合数据类型的列,该数据类型可以给出一些有意义的顺序,即排序(整数、日期等)。
列中的数据是否普遍增加并不重要。如果您在列上创建索引,索引将创建它自己的数据结构,该结构将简单地引用表中的实际项目,而不考虑存储顺序(非聚集索引)。然后,例如可以对您的索引数据结构执行二进制搜索以提供快速检索。
还可以创建一个“聚集索引”,对您的数据进行物理重新排序。但是,每个表只能有一个,而可以有多个非聚集索引。
Guid
上创建索引,但索引将被排序以优化 Seek 操作。当插入的数据是顺序的(如 IDENTITY 列)时,可以简单地附加索引,碎片风险相对较低,但是 Guid
值通常是随机值,这意味着每次新插入都会导致索引碎片化,需要重新排序索引。对于大型数据库,这可能会导致需要主动管理的严重性能或维护问题。使用顺序键而不是 Guid
可以简化长期管理。
您的主键应始终是索引。 (事实上,如果它没有被 MS SQL 自动索引,我会感到惊讶。)您还应该经常索引您 SELECT
或 ORDER
的列;它们的目的是快速查找单个值和更快的排序。
索引too
许多列的唯一真正危险是减慢对大表中行的更改,因为索引也都需要更新。如果您真的不确定要索引什么,只需为最慢的查询计时,查看最常使用的列,然后为它们编制索引。然后看看他们的速度有多快。
出于多种原因,按升序或降序排序的数字数据类型是很好的索引。首先,数字通常比字符串(varchar、char、nvarchar 等)计算速度更快。其次,如果您的值没有排序,则可能需要对行和/或页面进行洗牌以更新您的索引。这是额外的开销。
如果您使用 SQL Server 2005 并设置使用 uniqueidentifiers (guids),并且不需要它们是随机的,请查看顺序 uniqueidentifier 类型。
最后,如果您谈论的是聚集索引,那么您谈论的是物理数据的种类。如果你有一个字符串作为你的聚集索引,那可能会变得很难看。
旧的经验法则是在 WHERE、ORDER BY 和 GROUP BY 子句中经常使用的列,或者在连接中经常使用的任何列。请记住,我指的是索引,而不是主键
不要给出一个“香草味”的答案,但这真的取决于你如何访问数据
如果您使用 GUID,它应该会更快。假设你有记录
100 200 3000 ....
如果你有索引(二分查找,你可以在 O(lg n) 时间内找到你要查找的记录的物理位置,而不是按顺序查找 O(n) 时间。这是因为你不知道你有哪些记录在你的桌子上。
最佳索引取决于表的内容以及您要完成的任务。
举个例子 一个成员数据库,其主键是成员社会保障号。我们选择 SS 是因为应用程序主要以这种方式引用个人,但您还想创建一个搜索功能,该功能将利用成员的名字和姓氏。然后我建议在这两个字段上创建一个索引。
您应该首先找出要查询的数据,然后确定需要索引的数据。
WHERE
、JOINS
或HAVING
的列创建索引?WHERE
子句中我正在检查一个字段的值,而它的列只能取两个值,那么我应该索引那个二进制列吗?这似乎是错误的。