5

我正在尝试了解 MySQL 中的索引。我知道在表中创建的索引可以加快查询的执行速度,并且可以减慢行的插入和更新速度。

创建索引时,我在一个名为authors包含 ( AuthorNum, AuthorFName, AuthorLName, ...)的表上使用了此查询

Create index Index_1 on Authors ([What to put here]);

我知道我必须输入一个列名,但是哪个?

当用户查询表或什么时,我是否必须将要比较的列名放在 Where 语句中?

4

5 回答 5

10

索引剖析

索引是数据库中不同的数据结构,是数据冗余。其主要目的是通过独立于物理排序的逻辑排序来提供索引数据的有序表示。我们使用双向链表和称为平衡搜索树(B-tree)的树结构来做到这一点。B 树很好,因为它们保持数据排序并允许在对数时间内进行搜索、访问、插入和删除。由于双向链表,我们可以根据需要在索引上轻松地向后或向前进行各种查询。插入变得简单,因为我们只需要重新排列指向不同数据片段的指针。数据库使用这些双向链表来连接叶节点(通常在 B+ 树或 B 树中),每个叶节点存储在一个页面中,并在叶子节点之间建立逻辑顺序。像这样的操作UPDATE或者INSERT变慢,因为它们实际上是文件系统中的两个写入操作(一个用于表数据,一个用于索引数据)。

使用 WHERE 定义最佳索引

要定义最佳索引,您不仅必须了解索引的工作原理,还必须了解应用程序如何查询数据。WHERE例如,您必须知道子句中出现的列组合。

LAST_NAME查询和列的一个常见限制是FIRST_NAME区分大小写。例如,与其进行精确搜索,Hotinger我们更愿意匹配所有结果HoTingEr,诸如此类。WHERE这在一个子句中很容易做到:我们只是说WHERE UPPER(LAST_NAME) = UPPER('Hotinger')

但是,如果我们定义一个索引LAST_NAME和查询,它实际上会运行全表扫描,因为查询不是 onLAST_NAME而是 on UPPER(LAST_NAME)。从数据库的角度来看,这是完全不同的。因此,在这种情况下,您应该UPPER(LAST_NAME)改为定义索引。

索引不一定必须用于一列。例如,如果主键是复合键(由多列组成),它将创建一个连接索引,也称为组合索引。请注意,级联索引的顺序对其可用性和可伸缩性有重大影响,因此必须谨慎选择。基本上,排序应该与WHERE子句中的排序方式相匹配。

使用 LIKE 定义最佳索引

通配符的位置有很大的不同。 LIKE子句在树遍历期间只使用通配符之前的字符;其余的不会缩小扫描的索引范围。子句前缀的选择性LIKE越强,扫描的索引就越窄。这使得索引查找更快。作为提示,请避免 LIKE使用通配符开头的子句,例如"%OTINGER%" For full-text search、MySQL 提供MATCHAGAINST关键字。从 MySQL 5.6 开始,您可以拥有全文索引。查看MySQL 的Full-Text Search Functions以获得有关索引这些结果的更深入讨论。

于 2013-10-30T12:50:41.180 回答
2

是的,通常您需要在WHERE查询子句中比较的列或列上建立索引以加快查询速度。

如果按 搜索AuthorFName,则在该列上创建索引。如果他们按 搜索AuthorLName,则您在该列上创建索引。

不过,在这种情况下,您应该查看的是FULLTEXT index。这将允许用户输入模糊查询,这将返回一些按相关性排序的结果。

来自MySQL 手册

索引用于快速查找具有特定列值的行。如果没有索引,MySQL 必须从第一行开始,然后读取整个表以查找相关行。桌子越大,成本越高。如果表有相关列的索引,MySQL 可以快速确定要在数据文件中间寻找的位置,而无需查看所有数据。如果一个表有 1,000 行,这至少比顺序读取快 100 倍。如果您需要访问大部分行,顺序读取会更快,因为这样可以最大限度地减少磁盘寻道。

于 2013-10-30T12:20:25.653 回答
2

限长指数:

当使用text列或非常大varchar的列时,您将无法在text/的整个长度上创建索引varchar,存在一些限制(长度约为 1024 个 ASCII 字符)。

在这种情况下,您可以在索引声明中指定长度。

CREATE INDEX `my_limited_length_index` ON `my_table`(`long_text_content`(512));
-- please notice the use of the numeric length of the index after the column name

处理值索引(显然在 PostgreSQL 而不是 MySQL 中可用):

索引不是专门从一列构建的,有些可能是从多列构建的,而另一些可能是从一列的一些信息构建的。例如,如果您有一个完整的datetime列,但您知道您只会过滤记录,date您可以基于该datetime列构建索引,但只包含date信息。

-- `my_table` has a `created` column of type timestamp
CREATE INDEX `my_date_created` ON `my_table`(DATE(`created`));
-- please notice the use of the DATE function which extracts only
-- the date from the `created` timestamp
于 2013-10-30T12:28:30.237 回答
2

索引通常意味着 B-Tree。了解 B-Tree 的结构,你就会明白索引能做什么,不能做什么。

在您的特定情况下:

  • WHERE AuthorLName = 'something'并且WHERE AuthorLName LIKE 'something%'可以通过 {AuthorLName} 上的索引来加速。
  • WHERE AuthorLName = 'something AND AuthorFName = 'something else'可以通过 {AuthorLName, AuthorFName} 或 {AuthorFName, AuthorLName} 上的复合索引来加速。
  • WHERE AuthorLName = 'something OR AuthorFName = 'something else'(这没有多大意义,但在这里作为示例)可以通过拥有两个索引来加速:在 {AuthorLName}{AuthorFName} 上。
  • WHERE AuthorLName LIKE '%something'不能通过 B-Tree 索引加速(cunside 全文索引)。
  • ETC...

使用索引,卢克!比在简单的 SO 帖子中更彻底地处理该主题。

于 2013-10-30T12:29:30.573 回答
0

索引应跨越您将在 WHERE 语句中使用的列。

为了更好地理解,这里有一个例子:

SELECT * FROM Authors WHERE AuthorNum > 10 AND AuthorLName LIKE 'A%';
SELECT * FROM Authors WHERE AuthorLName LIKE 'Be%';

如果您经常使用上面显示的查询,强烈建议您有两个索引:

Create index AuthNum_AuthLName_Index on Authors (AuthorNum, AuthorLName);
Create index AuthLName_Index on Authors (AuthorLName);

WHERE要记住的关键事项:索引应具有语句中使用的相同列组合

于 2013-10-30T12:22:16.210 回答