当我在列上创建索引时会发生什么?

Mar*_* AJ 6 mysql sql indexing

我已经问过关于索引的多个问题.像这样的东西:

以下查询会从此索引中受益吗? mytable(col1, col2, col3)

. . . WHERE col1 = ? AND col3 = ?
. . . WHERE col2 = ?
. . . WHERE col1 IN (?, ?)
. . . WHERE col3 = ? AND col1 NOT IN (?, ?)
. . . WHERE col1 = ? OR col2 = ?
. . . WHERE col2 = ? AND col1 = ?
. . . WHERE col1 = ? AND col2 > ?
. . . WHERE col1 = ? AND col3 > ?

-- each question was containing one of these queries ;-)
Run Code Online (Sandbox Code Playgroud)

每当我得到该问题中提到的特定查询的答案时,我仍然无法判断这样的索引对于这样的查询是否有用.(或如何使其更优化)

所以我决定问这个问题,想知道后台.当我在列上创建索引时会发生什么?索引是由什么组成的?多列索引包含哪些行(因为顺序很重要)?它如何工作导致查询更快?

实际上我需要一些有关索引的信息,这使我能够如何确定查询的正确索引(多列或单列).

注意:我有一些经验可以使用EXPLAIN.是的,我知道使用EXPLAIN在这些情况下非常有用.现在我只需要一些进一步的信息.

sca*_*dge 1

此评估仅基于您显示的 where 子句...可以根据选择列进行更改

\n\n
    . . . WHERE col1 = ? AND col3 = ?               yes partial (only col1)\n    . . . WHERE col2 = ?                            no\n    . . . WHERE col1 IN (?, ?)                      yes \n    . . . WHERE col3 = ? AND col1 NOT IN (?, ?)     yes partial (only col1)\n    . . . WHERE col1 = ? OR col2 = ?                yes\n    . . . WHERE col2 = ? AND col1 = ?               yes\n    . . . WHERE col1 = ? AND col2 > ?               yes \n    . . . WHERE col1 = ? AND col3 > ?               yes partial (only col1)\n
Run Code Online (Sandbox Code Playgroud)\n\n

为了更好地解释索引如何在 mysql 上工作,你可以看到这个参考http://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html

\n\n

来自文档

\n\n
\n

MySQL 使用索引来执行以下操作:

\n\n

快速查找与 WHERE 子句匹配的行。

\n\n

从考虑中消除行。如果在多个索引之间进行选择,MySQL 通常会使用找到最少行数的索引(最具选择性的索引)。如果表具有多列索引,则优化器可以使用索引的任何最左边的前缀来查找行。例如,如果您在 (col1, col2, col3) 上有一个三列索引,则您在 (col1)、(col1, col2) 和 (col1, col2, col3) 上具有索引搜索功能。有关详细信息,请参阅第 9.3.5 节,\xe2\x80\x9c 多列索引\xe2\x80\x9d。

\n\n

执行连接时从其他表检索行。如果将列声明为相同的类型和大小,MySQL 可以更有效地使用列上的索引。在此上下文中,如果 VARCHAR 和 CHAR 声明为相同的大小,则将它们视为相同。例如,\n VARCHAR(10) 和 CHAR(10) 的大小相同,但 VARCHAR(10) 和\n CHAR(15) 的大小不同。

\n\n

对于非二进制字符串列之间的比较,两列应使用相同的字符集。例如,将 utf8 列与 latin1 列进行比较会排除索引的使用。

\n\n

如果在不进行转换的情况下无法直接比较值,则比较不同的列(例如,将字符串列与时间列或数字列进行比较)可能会阻止使用索引。\n 对于数字列中的给定值(例如 1),它可能与字符串列中的任意数量的值进行比较,例如“1”、“1”、“00001”或\n\'01.e1\'。这排除了对字符串列使用任何索引。

\n\n

查找特定索引列的 MIN() 或 MAX() 值\n key_col。这是由预处理器优化的,该预处理器检查您是否在索引中 key_col 之前出现的所有关键部分上使用 WHERE key_part_N =constant。在这种情况下,MySQL 对每个 MIN() 或 MAX() 表达式进行单键查找,并将其替换为常量。如果所有表达式都替换为常量,则查询将立即返回。例如:

\n\n

如果排序或分组是在可用索引的最左侧前缀上完成的(例如 ORDER BY key_part1,\n key_part2),则对表进行排序或分组。如果所有密钥部分后面都跟有 DESC,则按相反的顺序读取密钥。请参阅第 9.2.1.15 节,\xe2\x80\x9cORDER BY Optimization\xe2\x80\x9d 和\n 第 9.2.1.16 节,\xe2\x80\x9cGROUP BY Optimization\xe2\x80\x9d。

\n\n

在某些情况下,可以优化查询以检索值,而无需查询数据行。(为查询提供所有必需结果的索引称为覆盖索引。)如果查询仅使用表中包含在某个索引中的列,则可以从索引树中检索选定的值为了更快的速度:

\n
\n