我试图理解MySQL中的索引。我知道在表中创建的索引可以加快执行查询的速度,并且可以减慢行的插入和更新速度。
创建索引时,我在名为authors
的表上使用了此查询,该表包含(AuthorNum
,AuthorFName
,AuthorLName
,...)
Create index Index_1 on Authors ([What to put here]);
我知道我必须添加一个列名,但哪一个?
当用户查询表或什么时,我是否必须在Where语句中放置要比较的列名?
答案 0 :(得分:9)
索引是数据库中的独特数据结构,是数据冗余。其主要目的是通过逻辑排序提供索引数据的有序表示,该逻辑排序独立于物理排序。我们使用双向链表和称为平衡搜索树(B树)的树结构来完成此操作。 B树很好,因为它们可以对数据进行排序,并允许在对数时间内进行搜索,访问,插入和删除。由于双向链表,我们可以根据需要在索引上轻松地向后或向前查找各种查询。插入变得简单,因为我们只需重新排列指向不同数据的指针。数据库使用这些双向链表来连接叶节点(通常在B +树或B树中),每个叶节点存储在页面中,并在叶节点之间建立逻辑排序。 UPDATE
或INSERT
之类的操作变慢,因为它们实际上是文件系统中的两个写操作(一个用于表数据,一个用于索引数据)。
要定义最佳索引,您不仅必须了解索引的工作方式,还必须了解应用程序如何查询数据。例如,您必须知道WHERE
子句中出现的列组合。
对LAST_NAME
和FIRST_NAME
列的查询的常见限制是区分大小写。例如,我们不想像Hotinger
那样进行精确搜索,而是希望匹配所有结果,例如HoTingEr
等。这在WHERE
子句中很容易实现:我们只是说WHERE UPPER(LAST_NAME) = UPPER('Hotinger')
但是,如果我们定义LAST_NAME
和查询的索引,它实际上会运行全表扫描,因为查询不在LAST_NAME
上,而在UPPER(LAST_NAME)
上。从数据库的角度来看,这是完全不同的。因此,在这种情况下,您应该在UPPER(LAST_NAME)
上定义索引。
索引不一定是一列。例如,如果主键是复合键(由多列组成),则它将创建连接索引,也称为组合索引。请注意,连锁索引的排序对其可用性和可伸缩性具有重大影响,因此必须谨慎选择。基本上,排序应该与WHERE
子句中的排序方式相匹配。
通配符的位置有很大的不同。 LIKE
子句仅在树遍历期间使用之前通配符中的字符;其余的不会缩小扫描的索引范围。 LIKE
子句的前缀越具有选择性,扫描索引就越窄。这使索引查找更快。作为提示,避免带有LIKE
等通配符的 "%OTINGER%"
子句对于全文搜索,MySQL提供MATCH
和AGAINST
个关键字。从MySQL 5.6开始,您可以拥有全文索引。请查看MySQL的Full-Text Search Functions,以获得有关索引这些结果的更深入讨论。
答案 1 :(得分:2)
是的,通常您需要在查询的WHERE
子句中比较的一列或多列的索引,以加快查询速度。
如果按AuthorFName
搜索,则在该列上创建索引。如果他们按AuthorLName
搜索,则您在该列上创建索引。
在这种情况下,也许您应该关注的是FULLTEXT index。这将允许用户输入模糊查询,这将返回按相关性排序的许多结果。
来自MySQL Manual:
索引用于快速查找具有特定列值的行。 如果没有索引,MySQL必须从第一行开始然后读取 通过整个表来查找相关的行。越大了 表,这个成本越多。如果表具有列的索引 有问题的是,MySQL可以快速确定要寻求的位置 数据文件的中间,而不必查看所有数据。如果 一个表有1000行,这比阅读快至少100倍 顺序。如果您需要访问大多数行,则更快 按顺序读取,因为这可以最大限度地减少磁盘搜索。
答案 2 :(得分: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
索引不是专门从一列构建的,有些可能是从多列构建的,而其他列可能只是根据列的一些信息构建的。例如,如果您有一个完整的datetime
列,但您知道您只想按date
过滤记录,则可以根据datetime
列构建索引,但只包含{{1} }} info。
date
答案 3 :(得分:2)
索引通常表示B树。理解B树的结构,你就会明白索引能做什么和不能做什么。
在您的特定情况下:
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索引(cunsider全文索引)加速。请参阅Use The Index, Luke!,了解对该主题的更彻底的处理,而不是简单的SO帖子。
答案 4 :(得分: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
语句中使用的列的相同组合