ChatGPT解决这个技术问题 Extra ChatGPT

哪些列通常可以制作好的索引?

作为我试图了解索引的“What are indexes and how can I use them to optimise queries in my database?”的后续,哪些列是好的索引候选?专门针对 MS SQL 数据库?

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


W
William Merfalen

索引可以在查询优化和从表中快速搜索结果中发挥重要作用。最重要的一步是选择要索引的列。有两个主要的地方我们可以考虑索引: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 日):

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

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

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

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


谢谢 Somnath,这是否意味着只应为我们计划使用 WHEREJOINSHAVING 的列创建索引?
是的,对您计划使用 WHERE、JOINS 或 HAVING 的列使用索引。但也要记住,所有条件列都不需要索引。有时 where 条件列仅使用一次,因此它可能不需要索引,而其他条件列在许多查询中使用,因此更喜欢对该列进行索引。
答案将受益于在 TL;DR 部分中放置“WHERE 子句中引用的列和 JOIN 子句中使用的列”。
所以你是说如果在我的 WHERE 子句中我正在检查一个字段的值,而它的列只能取两个值,那么我应该索引那个二进制列吗?这似乎是错误的。
@AjaxLeung:记住 Knuth 的格言“过早优化是万恶之源。”。您可以在二进制列上创建索引,但它应该取决于成本(如插入、更新时间)。如果您的业务逻辑通常依赖于该二进制开关,则可能需要二进制列具有索引。
C
Community

有些人在这里回答了类似的问题:How do you know what a good index is?

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

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

祝你好运!


P
Plasmer

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

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

列或列具有高度的唯一性

您经常需要为列查找某个值或值范围。

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

您正在选择表中较大的 % (>10-20%) 行

额外的空间使用是一个问题

您希望最大限度地提高插入性能。表上的每个索引都会降低插入和更新性能,因为每次数据更改时都必须更新它们。

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


字符串搜索值可以在字符串内的任何位置可能使其在这种情况下不使用这些索引。
n
nawfal

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

这包括:外键 -

select * from tblOrder where status_id=:v_outstanding

描述性字段 -

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

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

select * from tblOrder where paidYN='N'

您对外键的明确提及确实为我考虑加入问题扫清了思路。
Z
Zooba

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

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

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

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


j
jwanagel

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

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


A
Ash

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

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

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


好吧,那并不完全准确。您可以轻松地在 GUID 列上创建常规的非聚集索引 - 为什么不呢?如果您将 GUID 用作集群键(例如,用于 CLUSTERED INDEX),则 GUID 有一个很大的缺点——那么它的使用是灾难性的。
可以Guid 上创建索引,但索引将被排序以优化 Seek 操作。当插入的数据是顺序的(如 IDENTITY 列)时,可以简单地附加索引,碎片风险相对较低,但是 Guid 值通常是随机值,这意味着每次新插入都会导致索引碎片化,需要重新排序索引。对于大型数据库,这可能会导致需要主动管理的严重性能或维护问题。使用顺序键而不是 Guid 可以简化长期管理。
E
Eevee

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

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


I
Ian Suttle

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

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

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


c
curtisk

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

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


M
Milhous

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

100 200 3000 ....

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


J
Joseph

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

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

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