了解MySQL中的索引

时间:2013-10-30 12:12:09

标签: mysql sql indexing

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

创建索引时,我在名为authors的表上使用了此查询,该表包含(AuthorNumAuthorFNameAuthorLName,...)

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

我知道我必须添加一个列名,但哪一个?

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

5 个答案:

答案 0 :(得分:9)

指数剖析

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

使用WHERE

定义最佳索引

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

LAST_NAMEFIRST_NAME列的查询的常见限制是区分大小写。例如,我们不想像Hotinger那样进行精确搜索,而是希望匹配所有结果,例如HoTingEr等。这在WHERE子句中很容易实现:我们只是说WHERE UPPER(LAST_NAME) = UPPER('Hotinger')

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

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

使用LIKE定义最佳索引

通配符的位置有很大的不同。 LIKE子句仅在树遍历期间使用之前通配符中的字符;其余的不会缩小扫描的索引范围。 LIKE子句的前缀越具有选择性,扫描索引就越窄。这使索引查找更快。作为提示,避免带有LIKE等通配符的 "%OTINGER%"子句对于全文搜索,MySQL提供MATCHAGAINST个关键字。从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

处理后的价值指数(显然在PostgreSQL中可用而不是MySQL):

索引不是专门从一列构建的,有些可能是从多列构建的,而其他列可能只是根据列的一些信息构建的。例如,如果您有一个完整的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语句中使用的列的相同组合