参考:https://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html
索引(Indexs)
一、作用(轻定义):索引用于快速查找具有特定列值的行。没有索引,MySQL必须从第一行开始,然后通读整个表以找到相关的行。表越大,花费时间越长。如果表中有相关??列的索引,MySQL可以快速确定要在数据文件中间查找的位置,而不必查看所有数据。这比顺序读取每一行要快得多。
二、数据结构:B+树(官方写的是B树)-与二叉树不同:多个分叉
- 参考:https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_b_tree
- 与存储引擎的关系:InnoDB、MyIsAM,Memory也可以使用(但一般使用哈希表会更合适)。B树更适合范围查询,哈希表更适合值匹配
三、mysql具体使用索引做什么
-
WHERE中作为查询条件
快速查找与子句匹配的行。 -
从考虑中消除行(possible_keys中有多个可考虑的索引的时候,mysql通常会选择最少行数的索引)。最具 选择性的(https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_selectivity)索引)。
-
如果表具有多列索引,那么优化器可以使用索引的任何最左前缀来查找行。举例来说,如果你有一个三列的索引
(col1, col2, col3)
,你有索引的搜索功能(col1)
,(col1, col2)
以及(col1, col2, col3)
。有关更多信息,请参见 第8.3.5节“多列索引”(https://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html)。【这个指的应该是组合索引,会使用最左匹配,优先用组合索引最左的进行匹配】 -
执行联接时从其他表中检索行。如果声明相同的类型和大小,MySQL可以更有效地在列上使用索引。在这种情况下,
VARCHAR
与CHAR
被认为是相同的,如果它们被声明为相同的大小。例如,VARCHAR(10)
和CHAR(10)
是相同的大小,但是VARCHAR(10)
和CHAR(15)
不是。【应该是指用于连接两个表的字段大小一致】对于非二进制字符串列之间的比较,两个列应使用相同的字符集。例如,将一
utf8
列与一latin1
列进行比较会排除使用索引。如果不能不通过转换直接比较值,则比较不同的列(例如,将字符串列与时间或数字列进行比较)可能会阻止使用索引。对于给定的值,如
1
在数值列,它可能比较等于在字符串列,例如任何数量的值‘1‘
,‘ 1‘
,‘00001‘
,或‘01.e1‘
。这排除了对字符串列使用任何索引的可能性。 -
查找特定索引列的
MIN()
或MAX()
值key_col
。这由预处理器优化,该预处理器检查您是否正在 索引中之前出现的所有关键部分上使用。在这种情况下,MySQL为每个表达式或 表达式执行一次键查找,并将其替换为常量。如果所有表达式都用常量替换,查询将立即返回。例如:WHERE
key_part_N
=constant
key_col
MIN()
MAX()
SELECT MIN(key_part2),MAX(key_part2) FROM tbl_name WHERE key_part1=10;
-
如果排序或分组是在可用索引的最左前缀(例如)上完成的,则对表进行排序或分组 。如果所有关键部分后面都有,则按相反顺序读取密钥。请参见 第8.2.1.14节“按优化排序”和 第8.2.1.15节“按优化分组”。
ORDER BY
key_part1
,key_part2
DESC
-
在某些情况下,可以优化查询以检索值而无需查询数据行。(为查询提供所有必要结果的索引称为 覆盖索引。)如果查询仅从表中使用某些索引中包含的列,则可以从索引树中检索所选值,以提高速度:
SELECT key_part3 FROM tbl_name WHERE key_part1=1
附录:
回表:比如过滤条件是name,查询的字段是age,扫描b+树之后获取到的主键id,再通过主键ID去扫描出数据
索引覆盖:查询的字段直接在索引中,不需要回表查询;以回表的例子来看,我们把查询的字段改为主键id,那就不需要再扫描数据
最左匹配:一般用于优化过滤,优先过滤数据较少的表
组合索引:结合最左匹配,一样可以通过优先级进行优化。低版本中查询的时候根据组合索引的字段过滤顺序会影响效率,高版本之后就没有影响了
索引下推:一般是指组合索引中,两个过滤条件命中的情况下,会一次过滤,而不是多次回表过滤