MySQL/MariaDB数据库的索引工作原理和优化

摘要:
否则将追究法律责任。频繁出现在where子句中的列可以考虑使用索引。按照翻译,B通常认为是Balance的简称。fr=aladdin4˃.B+树B+树是一种树数据结构,通常用于数据库和操作系统的文件系统中。B+树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。InnoDB中,数据文件本身就是按主键索引存储的,叶子节点中保存的就是数据记录。

MySQL/MariaDB数据库的索引工作原理和优化

作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

实际工作中索引这个技术是影响服务器性能一个非常重要的指标,因此我们得花时间去了解一下索引的相关特性。索引是一把双刃剑用得好可以快速查询数据,用得不好数据库查询速度不仅慢还降低服务器性能,浪费磁盘空间。

一.索引概述

1>.什么是索引

  索引是特殊数据结构,定义在查找时作为查找条件的字段,在MySQL又称为键key,索引通过存储引擎实现。
索引可以看作是一本字典的目录,为了快速检索,用空间换时间,显著提高查询效率。
可以为一列或者多列字段设置索引。
不是说有了索引性能就一定能提升,有了索引咱们还得会利用索引,用正确的方法使用索引,使用不当反而会降低服务器性能。

2>.索引的优点

索引可以降低服务需要扫描的数据量,减少了IO次数

索引可以帮助服务器避免排序和使用临时表
索引可以帮助将随机I
/O转为顺序I/O

3>.索引的缺点

  占用额外空间,影响插入速度

二.索引类型

主键索引:
  主键会自动建立主键索引,主键本身就是为了快速定位唯一记录的。
唯一索引:
  表中的索引列组成的索引必须唯一,但可以为空,非空值必须唯一
普通索引:
  没有唯一性的要求,就是建了一个字典的目录而已。
联合索引:
  多个字段组合创建索引,使用条件查询时,先匹配左边字段
全文索引:
  MyISAM使用,对Char、Varchar、TEXT类型使用 空间索引,SPATIAL,基本不用。 
聚簇(集)索引、非聚簇索引:
  数据和索引是否存储在一起
稠密索引、稀疏索引:
  是否索引了每一个数据项
简单索引、组合索引:
  左前缀索引:取前面的字符做索引
  覆盖索引:从索引中即可取出要查询的数据,性能高
 其他索引:
  B+TREE、HASH、R TREE
  
在MySQL中,InnoDB和MyISAM的索引数据结构可以使用Hash或BTree,innodb默认是BTree。 Hash时间复杂度是O(
1),但是只能进行精确匹配,也就是Hash值的匹配,比如范围匹配就没办法了,   
hash值无序所以无法知道原有记录的顺序。Hash问题较多。 BTree索引,以B
+树为存储结构。   
虽然,索引可以提高查询所读,但是却影响增删改的效率,因为需要索引更新或重构。频繁出现在 where子句中的列可以考虑使用索引。要避免把性别这种字段设索引。

1>.二叉树

MySQL/MariaDB数据库的索引工作原理和优化第1张

1)每个结点最多2棵子树
    二叉树不存在度数大于2的结点。
(2)它是有序树,左子树,右子树是顺序的,不能交换次序
(3)即使某个节点只有一棵子树,也要确定它是左子树还是右子树
(4)二叉树的物种基本形态
    1)空二叉树
    2)只有一个根结点
    3)根结点只有左子树
    4)根结点只有右子树
    5)根结点有左子树和右子树
博主推荐阅读:
  https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E6%A0%91
  https://www.cnblogs.com/yinzhengjie/p/10960896.html

2>.红黑树(又叫自平衡二叉树)

MySQL/MariaDB数据库的索引工作原理和优化第2张

博主推荐阅读:
  https://baike.baidu.com/item/%E7%BA%A2%E9%BB%91%E6%A0%91

3>.B-tree索引(B-tree(多路搜索树,并不是二叉的)

B-tree(多路搜索树,并不是二叉的)是一种常见的数据结构。使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。按照翻译,B 通常认为是Balance的简称。这个数据结构一般用于数据库的索引,综合效率较高。
博主推荐阅读:
  https://baike.baidu.com/item/B-tree/6606402?fr=aladdin

4>.B+树(MySQL数据库默认使用该索引)

MySQL/MariaDB数据库的索引工作原理和优化第3张

B+树是一种树数据结构,通常用于数据库和操作系统的文件系统中。B+树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+树元素自底向上插入,这与二叉树恰好相反。
  B+树节点组织成一棵树。节点分为内部节点和叶子节点。
  内部节点不存储数据,叶子节点不存储指针。
如下图所示,每个leaf node保存数据,所有的leaf node组织成链表。假设读取16到22的数据,找到18后,顺着链表 往后遍历读取即可。
InnoDB中,数据文件本身就是按主键索引存储的,叶子节点中保存的就是数据记录。 如果在其他字段上定义B
+Tree索引,叶子节点的数据记录的是主键,这种称为辅助索引。 B+Tree索引:   顺序存储,每一个叶子节点到根结点的距离是相同的;左前缀索引,适合查询范围类的数据 可以使用B+Tree索引的查询类型:   全值匹配:精确所有索引列,如:姓yin,名zhengjie,年龄18   匹配最左前缀:即只使用索引的第一列,如:姓yin   匹配列前缀:只匹配一列值开头部分,如:姓以y开头的   匹配范围值:如:姓yin和姓ma之间   精确匹配某一列并范围匹配另一列:如:姓yin,名以x开头的   只访问索引的查询 B+Tree索引的限制:   如不从最左列开始,则无法使用索引,如:查找名为zhengjie,或姓为g结尾   不能跳过索引中的列:如:查找姓yin,年龄18的,只能使用索引第一列   如果查询中某个列是为范围查询,那么其右侧的列都无法再使用索引:如:姓yin,名z%,年龄18,只能利用姓和名上面的索引 特别提示:   索引列的顺序和查询语句的写法应相匹配,才能更好的利用索引   为优化性能,可能需要针对相同的列但顺序不同创建不同的索引来满足不同类型的查询需求 博主推荐阅读:   https://baike.baidu.com/item/B+%E6%A0%91/7845683

MySQL/MariaDB数据库的索引工作原理和优化第4张

5>.Hash索引

Hash索引:
  基于哈希表实现,只有精确匹配索引中的所有列的查询才有效,索引自身只存储索引列对应的哈希值和数据指针,索引结构紧凑,查询性能好
Memory存储引擎支持显式hash索引,InnoDB和MyISAM存储引擎不支持
适用场景:
  只支持等值比较查询,包括=, <=>, IN()
不适合使用hash索引的场景
  不适用于顺序查询:索引存储顺序的不是值的顺序
  不支持模糊匹配
  不支持范围查询
  不支持部分索引列匹配查找:如A,B列索引,只查询A列索引无效

6>.空间数据索引R-Tree( Geospatial indexing )

MyISAM支持地理空间索引,可以使用任意维度组合查询,使用特有的函数访问,常用于做地理数据存储,使用不多

InnoDB从MySQL5.7之后也开始支持

7>.全文索引(FULLTEXT)

在文本中查找关键词,而不是直接比较索引中的值,类似搜索引擎

InnoDB从MySQL
5.6之后也开始支持

8>.聚簇和非聚簇索引

MySQL/MariaDB数据库的索引工作原理和优化第5张

9>.聚簇和非聚簇索引,主键和二级索引

MySQL/MariaDB数据库的索引工作原理和优化第6张

10>.冗余和重复索引

冗余索引:(A),(A,B)
  重复索引:已经有索引,再次建立索引

11>.索引优化策略

独立地使用列:
尽量避免其参与运算,独立的列指索引列不能是表达式的一部分,也不能是函数的参数,在where条件中,始终将索引列单独放在比较符号的一侧
左前缀索引:
构建指定索引字段的左侧的字符数,要通过索引选择性来评估
索引选择性:
不重复的索引值和数据表的记录总数的比值
多列索引:
AND操作时更适合使用多列索引,而非为每个列创建单独的索引
选择合适的索引列顺序:
无排序和分组时,将选择性最高放左侧

12>.索引优化建议

只要列中含有NULL值,就最好不要在此例设置索引,复合索引如果有NULL值,此列在使用时也不会使用索引

尽量使用短索引,如果可以,应该制定一个前缀长度
对于经常在where子句使用的列,最好设置索引
对于有多个列where或者order by子句,应该建立复合索引
对于like语句,以
%或者‘-’开头的不会使用索引,以%结尾会使用索引
尽量不要在列上进行运算(函数操作和表达式操作)  
尽量不要使用not in和
<>操作

13>.SQL语句性能优化

  查询时,能不要*就不用*,尽量写全字段名

大部分情况连接效率远大于子查询
多表连接时,尽量小表驱动大表,即小表
join大表
在有大量记录的表分页时使用limit
对于经常使用的查询,可以开启缓存
多使用explain和profile分析查询语句
查看慢查询日志,找出执行时间长的sql语句优化

三.管理索引实战

1>.创建测试数据

MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第8张
MariaDB [yinzhengjie]> CREATE TABLE  index_test (id INT auto_increment PRIMARY KEY,name CHAR(50),age INT DEFAULT 20);
Query OK, 0 rows affected (0.01sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]>DELIMITER $$
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> CREATE PROCEDUREpro_testlog() 
    -> BEGIN  
    -> DECLARE i INT;
    -> SET i = 1; 
    -> WHILE i < 100000 
    ->DO  
    ->     INSERT INTO index_test(name,age) VALUES (CONCAT('yinzhengjie',i),i); 
    ->     SET i = i +1; 
    -> END WHILE; 
    -> END$$
Query OK, 0 rows affected (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]>DELIMITER ;
MariaDB [yinzhengjie]> 
创建测试表及存储过程
MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第10张
MariaDB [yinzhengjie]> SELECT *FROM index_test;
Empty set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]>CALL pro_testlog;        #调用存储过程,往index_test表中写入测试数据
Query OK, 1 row affected (34.07sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SELECT * FROM index_test LIMIT 10;
+----+---------------+------+
| id | name          | age  |
+----+---------------+------+
|  1 | yinzhengjie1  |    1 |
|  2 | yinzhengjie2  |    2 |
|  3 | yinzhengjie3  |    3 |
|  4 | yinzhengjie4  |    4 |
|  5 | yinzhengjie5  |    5 |
|  6 | yinzhengjie6  |    6 |
|  7 | yinzhengjie7  |    7 |
|  8 | yinzhengjie8  |    8 |
|  9 | yinzhengjie9  |    9 |
| 10 | yinzhengjie10 |   10 |
+----+---------------+------+
10 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SELECT * FROM index_test GROUP BY id DESC LIMIT 10;
+-------+------------------+-------+
| id    | name             | age   |
+-------+------------------+-------+
| 99999 | yinzhengjie99999 | 99999 |
| 99998 | yinzhengjie99998 | 99998 |
| 99997 | yinzhengjie99997 | 99997 |
| 99996 | yinzhengjie99996 | 99996 |
| 99995 | yinzhengjie99995 | 99995 |
| 99994 | yinzhengjie99994 | 99994 |
| 99993 | yinzhengjie99993 | 99993 |
| 99992 | yinzhengjie99992 | 99992 |
| 99991 | yinzhengjie99991 | 99991 |
| 99990 | yinzhengjie99990 | 99990 |
+-------+------------------+-------+
10 rows in set (0.00sec)
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> CALL pro_testlog;        #调用存储过程,往index_test表中写入测试数据

2>.查看索引

MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第12张
MariaDB [yinzhengjie]>HELP SHOW INDEX 
Name: 'SHOW INDEX'
Description:
Syntax:
SHOW {INDEX | INDEXES |KEYS}
    {FROM |IN} tbl_name
    [{FROM |IN} db_name]
    [WHERE expr]
SHOW INDEX returns table index information. The format resembles that
of the SQLStatistics call inODBC. This statement requires some
privilege for any column inthe table.
You can use db_name.tbl_name as an alternative to the tbl_name FROM
db_name syntax. These two statements are equivalent:
SHOW INDEX FROM mytable FROM mydb;
SHOW INDEX FROM mydb.mytable;
The WHERE clause can be given to select rows using moregeneral
conditions, as discussed in
https://mariadb.com/kb/en/extended-show/.

You can also list a table's indexes with the mysqlshow -k db_name
tbl_name command.
URL: https://mariadb.com/kb/en/show-index/

MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> HELP SHOW INDEX
MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第14张
MariaDB [yinzhengjie]>DESC index_test;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| name  | char(50) | YES  |     | NULL    |                |
| age   | int(11)  | YES  |     | 20      |                |
+-------+----------+------+-----+---------+----------------+
3 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]>SHOW INDEXES FROM index_test;
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+--
-------------+| Table      | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |I
ndex_comment |+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+--
-------------+| index_test |          0 | PRIMARY  |            1 | id          | A         |       99659 |     NULL | NULL   |      | BTREE      |         |  
             |+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+--
-------------+1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]>SHOW INDEXES FROM index_testG
*************************** 1. row ***************************
        Table: index_test
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> SHOW INDEXES FROM index_testG
MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第16张
MariaDB [yinzhengjie]>SHOW INDEXES FROM index_testG
*************************** 1. row ***************************
        Table: index_test
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SELECT * FROM index_test WHERE id = 99999;      #由于主键就是索引,因此查询起来速度极快
+-------+------------------+-------+
| id    | name             | age   |
+-------+------------------+-------+
| 99999 | yinzhengjie99999 | 99999 |
+-------+------------------+-------+
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SELECT * FROM index_test WHERE age = 99999;      #不难发现,由于age并不是主键索引,因此查询起来速度明显有所降低
+-------+------------------+-------+
| id    | name             | age   |
+-------+------------------+-------+
| 99999 | yinzhengjie99999 | 99999 |
+-------+------------------+-------+
1 row in set (0.05sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SELECT * FROM index_test WHERE age = 99999;      #很显然,查询的不是主键索引的列速度会明显下降,如果第二次调用该语句时查询时间为0,那就得观察缓存是否开启了。
+-------+------------------+-------+
| id    | name             | age   |
+-------+------------------+-------+
| 99999 | yinzhengjie99999 | 99999 |
+-------+------------------+-------+
1 row in set (0.04sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SHOW VARIABLES LIKE 'query_cache%';            #查看缓存是否开启。
+------------------------------+---------+
| Variable_name                | Value   |
+------------------------------+---------+
| query_cache_limit            | 1048576 |
| query_cache_min_res_unit     | 4096    |
| query_cache_size             | 1048576 |
| query_cache_strip_comments   | OFF     |
| query_cache_type             | OFF     |
| query_cache_wlock_invalidate | OFF     |
+------------------------------+---------+
6 rows in set (0.00sec)
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> SELECT * FROM index_test WHERE id = 99999;      #由于主键就是索引,因此查询起来速度极快

3>.创建索引

MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第18张
MariaDB [yinzhengjie]>HELP CREATE INDEX
Name: 'CREATE INDEX'
Description:
Syntax:
CREATE [ONLINE|OFFLINE] [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
    [index_type]
    ON tbl_name (index_col_name,...)
    [index_option] ...
index_col_name:
    col_name [(length)] [ASC |DESC]
index_type:
    USING {BTREE |HASH}
index_option:
    KEY_BLOCK_SIZE [=] value
  |index_type
  |WITH PARSER parser_name
  | COMMENT 'string'
CREATE INDEX is mapped to an ALTER TABLE statement to create indexes.
See [HELP ALTER TABLE]. CREATE INDEX cannot be used to create a PRIMARY
KEY; use ALTER TABLE instead. For moreinformation about indexes, see
https://mariadb.com/kb/en/optimization-and-indexes/.

URL: https://mariadb.com/kb/en/create-index/

MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> HELP CREATE INDEX
MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第20张
MariaDB [yinzhengjie]> SHOW INDEXES FROMindex_testG
*************************** 1. row ***************************
        Table: index_test
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> CREATE INDEX my_index_test01 ON index_test(name(16));
Query OK, 0 rows affected (0.27sec)                
Records: 0  Duplicates: 0  Warnings: 0
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SHOW INDEXES FROMindex_testG
*************************** 1. row ***************************
        Table: index_test
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 2. row ***************************
        Table: index_test
   Non_unique: 1
     Key_name: my_index_test01
 Seq_in_index: 1
  Column_name: name
    Collation: A
  Cardinality: 99659
     Sub_part: 16
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
2 rows in set (0.00sec)
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> CREATE INDEX my_index_test01 ON index_test(name(16));
MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第22张
MariaDB [yinzhengjie]> SHOW INDEXES FROMindex_testG
*************************** 1. row ***************************
        Table: index_test
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SELECT * FROM index_test GROUP BY id DESC LIMIT 3;
+-------+------------------+-------+
| id    | name             | age   |
+-------+------------------+-------+
| 99999 | yinzhengjie99999 | 99999 |
| 99998 | yinzhengjie99998 | 99998 |
| 99997 | yinzhengjie99997 | 99997 |
+-------+------------------+-------+
3 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> EXPLAIN SELECT * FROM index_test WHERE name = 'yinzhengjie99999';    #我们发现该语句未用到任何索引。
+------+-------------+------------+------+---------------+------+---------+------+-------+-------------+
| id   | select_type | table      | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+------+-------------+------------+------+---------------+------+---------+------+-------+-------------+
|    1 | SIMPLE      | index_test | ALL  | NULL          | NULL | NULL    | NULL | 99659 | Using where |
+------+-------------+------------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> CREATE INDEX my_index_test02 ON index_test(name(16));            #紧接着我们创建一个在index_test表的name字段上创建一个前16个字符的索引.
Query OK, 0 rows affected (0.27sec)                
Records: 0  Duplicates: 0  Warnings: 0
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> EXPLAIN SELECT * FROM index_test WHERE name = 'yinzhengjie99999';       #我们发现该查询语句使用到咱们自己创建的索引啦。
+------+-------------+------------+------+-----------------+-----------------+---------+-------+------+-------------+
| id   | select_type | table      | type | possible_keys   | key             | key_len | ref   | rows | Extra       |
+------+-------------+------------+------+-----------------+-----------------+---------+-------+------+-------------+
|    1 | SIMPLE      | index_test | ref  | my_index_test02 | my_index_test02 | 49      | const |    1 | Using where |
+------+-------------+------------+------+-----------------+-----------------+---------+-------+------+-------------+
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SHOW INDEXES FROMindex_testG
*************************** 1. row ***************************
        Table: index_test
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 2. row ***************************
        Table: index_test
   Non_unique: 1
     Key_name: my_index_test02
 Seq_in_index: 1
  Column_name: name
    Collation: A
  Cardinality: 99659
     Sub_part: 16
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
2 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> EXPLAIN SELECT * FROM index_test WHERE name = 'yinzhengjie99999';   #我们发现该查询语句使用到咱们自己创建的索引啦。
MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第24张
MariaDB [yinzhengjie]> SHOW INDEXES FROMindex_testG
*************************** 1. row ***************************
        Table: index_test
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 2. row ***************************
        Table: index_test
   Non_unique: 1
     Key_name: my_index_test02
 Seq_in_index: 1
  Column_name: name
    Collation: A
  Cardinality: 99659
     Sub_part: 16
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
2 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> CREATE INDEX my_index_03_name_age ONindex_test(name,age);      #创建复合索引
Query OK, 0 rows affected (0.34sec)                
Records: 0  Duplicates: 0  Warnings: 0
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SHOW INDEXES FROMindex_testG
*************************** 1. row ***************************
        Table: index_test
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 2. row ***************************
        Table: index_test
   Non_unique: 1
     Key_name: my_index_test02
 Seq_in_index: 1
  Column_name: name
    Collation: A
  Cardinality: 99659
     Sub_part: 16
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 3. row ***************************
        Table: index_test
   Non_unique: 1
     Key_name: my_index_03_name_age
 Seq_in_index: 1
  Column_name: name
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 4. row ***************************
        Table: index_test
   Non_unique: 1
     Key_name: my_index_03_name_age
 Seq_in_index: 2
  Column_name: age
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
4 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> EXPLAIN SELECT * FROM index_test WHERE name = 'yinzhengjie10000';    #利用复合索引第一个字段查询,发现是可以利用到索引
+------+-------------+------------+------+--------------------------------------+----------------------+---------+-------+------+----------------
----------+| id   | select_type | table      | type | possible_keys                        | key                  | key_len | ref   | rows | Extra          
          |+------+-------------+------------+------+--------------------------------------+----------------------+---------+-------+------+----------------
----------+|    1 | SIMPLE      | index_test | ref  | my_index_test02,my_index_03_name_age | my_index_03_name_age | 151     | const |    1 | Using where; Us
ing index |+------+-------------+------------+------+--------------------------------------+----------------------+---------+-------+------+----------------
----------+1 row in set (0.00 sec)

MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> EXPLAIN SELECT * FROM index_test WHERE age = '10000';            #利用复合索引第二个字段查询,发现也是可以利用到索引,但是不推荐,因为有的时候我们使用复合索引第二个字段查询是查询不到的。具体案例参考下面的演示。
+------+-------------+------------+-------+---------------+----------------------+---------+------+-------+--------------------------+
| id   | select_type | table      | type  | possible_keys | key                  | key_len | ref  | rows  | Extra                    |
+------+-------------+------------+-------+---------------+----------------------+---------+------+-------+--------------------------+
|    1 | SIMPLE      | index_test | index | NULL          | my_index_03_name_age | 156     | NULL | 99659 | Using where; Using index |
+------+-------------+------------+-------+---------------+----------------------+---------+------+-------+--------------------------+
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> CREATE INDEX my_index_03_name_age ON index_test(name,age);      #创建复合索引
MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第26张
MariaDB [yinzhengjie]> SHOW INDEXES FROMindex_testG
*************************** 1. row ***************************
        Table: index_test
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 2. row ***************************
        Table: index_test
   Non_unique: 1
     Key_name: my_index_test02
 Seq_in_index: 1
  Column_name: name
    Collation: A
  Cardinality: 99659
     Sub_part: 16
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
2 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> DESCstudents;
+-----------+---------------------+------+-----+---------+----------------+
| Field     | Type                | Null | Key | Default | Extra          |
+-----------+---------------------+------+-----+---------+----------------+
| StuID     | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |
| Name      | varchar(50)         | NO   |     | NULL    |                |
| Age       | tinyint(3) unsigned | NO   |     | NULL    |                |
| Gender    | enum('F','M')       | NO   |     | NULL    |                |
| ClassID   | tinyint(3) unsigned | YES  |     | NULL    |                |
| TeacherID | int(10) unsigned    | YES  |     | NULL    |                |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.01sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SELECT * FROM students GROUP BY StuID DESC LIMIT 2;
+-------+-----------------------+-----+--------+---------+-----------+
| StuID | Name                  | Age | Gender | ClassID | TeacherID |
+-------+-----------------------+-----+--------+---------+-----------+
|    25 | 齐天大圣孙悟空        | 100 | M      |    NULL |      NULL |
|    24 | Xu Xian               |  27 | M      |    NULL |      NULL |
+-------+-----------------------+-----+--------+---------+-----------+
2 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> CREATE INDEX my_students_name_age ONstudents(name,age);    #创建一个复合索引,但是注意使用索引时最好不要直接使用后面那个属性。
Query OK, 0 rows affected (0.02sec)
Records: 0  Duplicates: 0  Warnings: 0
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> EXPLAIN SELECT * FROM students WHERE name = '齐天大圣孙悟空';    #我们使用复合索引的第一个name索引字段查询,发现执行SQL语句时可以利用到索引
+------+-------------+----------+------+----------------------+----------------------+---------+-------+------+-----------------------+
| id   | select_type | table    | type | possible_keys        | key                  | key_len | ref   | rows | Extra                 |
+------+-------------+----------+------+----------------------+----------------------+---------+-------+------+-----------------------+
|    1 | SIMPLE      | students | ref  | my_students_name_age | my_students_name_age | 152     | const |    1 | Using index condition |
+------+-------------+----------+------+----------------------+----------------------+---------+-------+------+-----------------------+
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> EXPLAIN SELECT * FROM students WHERE age = 100;          #我们使用复合索引的第二个age索引字段查询,发现执行SQL语句时却不可以使用索引啦!
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id   | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
|    1 | SIMPLE      | students | ALL  | NULL          | NULL | NULL    | NULL |   25 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> EXPLAIN SELECT * FROM students WHERE age = 100;          #我们使用复合索引的第二个age索引字段查询,发现执行SQL语句时却不可以使用索引啦!
MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第28张
MariaDB [yinzhengjie]> DESCstudents;
+-----------+---------------------+------+-----+---------+----------------+
| Field     | Type                | Null | Key | Default | Extra          |
+-----------+---------------------+------+-----+---------+----------------+
| StuID     | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |
| Name      | varchar(50)         | NO   |     | NULL    |                |
| Age       | tinyint(3) unsigned | NO   |     | NULL    |                |
| Gender    | enum('F','M')       | NO   |     | NULL    |                |
| ClassID   | tinyint(3) unsigned | YES  |     | NULL    |                |
| TeacherID | int(10) unsigned    | YES  |     | NULL    |                |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.01sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SELECT * FROMstudents;
+-------+-----------------------+-----+--------+---------+-----------+
| StuID | Name                  | Age | Gender | ClassID | TeacherID |
+-------+-----------------------+-----+--------+---------+-----------+
|     1 | Shi Zhongyu           |  22 | M      |       2 |         3 |
|     2 | Shi Potian            |  22 | M      |       1 |         7 |
|     3 | Xie Yanke             |  53 | M      |       2 |        16 |
|     4 | Ding Dian             |  32 | M      |       4 |         4 |
|     5 | Yu Yutong             |  26 | M      |       3 |         1 |
|     6 | Shi Qing              |  46 | M      |       5 |      NULL |
|     7 | Xi Ren                |  19 | F      |       3 |      NULL |
|     8 | Lin Daiyu             |  17 | F      |       7 |      NULL |
|     9 | Ren Yingying          |  20 | F      |       6 |      NULL |
|    10 | Yue Lingshan          |  19 | F      |       3 |      NULL |
|    11 | Yuan Chengzhi         |  23 | M      |       6 |      NULL |
|    12 | Wen Qingqing          |  19 | F      |       1 |      NULL |
|    13 | Tian Boguang          |  33 | M      |       2 |      NULL |
|    14 | Lu Wushuang           |  17 | F      |       3 |      NULL |
|    15 | Duan Yu               |  19 | M      |       4 |      NULL |
|    16 | Xu Zhu                |  21 | M      |       1 |      NULL |
|    17 | Lin Chong             |  25 | M      |       4 |      NULL |
|    18 | Hua Rong              |  23 | M      |       7 |      NULL |
|    19 | Xue Baochai           |  18 | F      |       6 |      NULL |
|    20 | Diao Chan             |  19 | F      |       7 |      NULL |
|    21 | Huang Yueying         |  22 | F      |       6 |      NULL |
|    22 | Xiao Qiao             |  20 | F      |       1 |      NULL |
|    23 | Ma Chao               |  23 | M      |       4 |      NULL |
|    24 | Xu Xian               |  27 | M      |    NULL |      NULL |
|    25 | 齐天大圣孙悟空        | 100 | M      |    NULL |      NULL |
+-------+-----------------------+-----+--------+---------+-----------+
25 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> CREATE UNIQUE INDEX my_unique_name_test03 ONstudents(name);    #创建唯一键索引(该列字段不允许重复)
Query OK, 0 rows affected (0.01sec)
Records: 0  Duplicates: 0  Warnings: 0
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]>  SHOW INDEXES FROMstudentsG
*************************** 1. row ***************************
        Table: students
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: StuID
    Collation: A
  Cardinality: 25
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 2. row ***************************
        Table: students
   Non_unique: 0
     Key_name: _unique_name_test03
 Seq_in_index: 1
  Column_name: Name
    Collation: A
  Cardinality: 25
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
2 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> DESCstudents;
+-----------+---------------------+------+-----+---------+----------------+
| Field     | Type                | Null | Key | Default | Extra          |
+-----------+---------------------+------+-----+---------+----------------+
| StuID     | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |
| Name      | varchar(50)         | NO   | UNI | NULL    |                |
| Age       | tinyint(3) unsigned | NO   |     | NULL    |                |
| Gender    | enum('F','M')       | NO   |     | NULL    |                |
| ClassID   | tinyint(3) unsigned | YES  |     | NULL    |                |
| TeacherID | int(10) unsigned    | YES  |     | NULL    |                |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> EXPLAIN SELECT * FROM students WHERE name = '齐天大圣孙悟空';
+------+-------------+----------+-------+---------------------+---------------------+---------+-------+------+-------+
| id   | select_type | table    | type  | possible_keys       | key                 | key_len | ref   | rows | Extra |
+------+-------------+----------+-------+---------------------+---------------------+---------+-------+------+-------+
|    1 | SIMPLE      | students | const | _unique_name_test03 | _unique_name_test03 | 152     | const |    1 |       |
+------+-------------+----------+-------+---------------------+---------------------+---------+-------+------+-------+
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> CREATE UNIQUE INDEX my_unique_name_test03 ON students(name);    #创建唯一键索引(该列字段不允许重复)

4>.删除索引

MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第30张
MariaDB [yinzhengjie]> HELP DROP INDEX
Name: 'DROP INDEX'
Description:
Syntax:
DROP [ONLINE|OFFLINE] INDEX index_name ONtbl_name
DROP INDEX drops the index named index_name from the tabletbl_name.
This statement is mapped to an ALTER TABLE statement to drop the index.
See [HELP ALTER TABLE].
To drop a primary key, the index name is always PRIMARY, which must be
specified as a quoted identifier because PRIMARY isa reserved word:
DROP INDEX `PRIMARY` ONt;
URL: https://mariadb.com/kb/en/drop-index/
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> HELP DROP INDEX
MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第32张
MariaDB [yinzhengjie]> SHOW INDEXES FROMindex_testG
*************************** 1. row ***************************
        Table: index_test
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 2. row ***************************
        Table: index_test
   Non_unique: 1
     Key_name: my_index_test01
 Seq_in_index: 1
  Column_name: name
    Collation: A
  Cardinality: 99659
     Sub_part: 16
       Packed: NULL
         Null: YES
   Index_type: BTREE
      Comment: 
Index_comment: 
2 rows in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> DROP INDEX my_index_test01 ONindex_test;          #删除指定表中的索引
Query OK, 0 rows affected (0.01sec)
Records: 0  Duplicates: 0  Warnings: 0
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SHOW INDEXES FROMindex_testG
*************************** 1. row ***************************
        Table: index_test
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 99659
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> DROP INDEX my_index_test01 ON index_test;          #删除指定表中的索引

4>.优化表空间

MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第34张
MariaDB [yinzhengjie]> HELP OPTIMIZE TABLE
Name: 'OPTIMIZE TABLE'
Description:
Syntax:
OPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE
    tbl_name [, tbl_name]...
OPTIMIZE TABLE should be used if you have deleted a large part ofa
table or if you have made many changes to a table with variable-length
rows (tables that have VARCHAR, VARBINARY, BLOB, or TEXTcolumns).
Deleted rows are maintained in a linked list and subsequent INSERT
operations reuse old row positions. You can use OPTIMIZE TABLE to
reclaim the unused space and to defragment the data file. After
extensive changes to a table, this statement may also improve
performance of statements that use the table, sometimes significantly.
This statement requires SELECT and INSERT privileges for the table.
OPTIMIZE TABLE is supported for partitioned tables, and you can use
ALTER TABLE ... OPTIMIZE PARTITION to optimize one ormore partitions;
for more information, see [HELP ALTER TABLE], and
http://dev.mysql.com/doc/refman/5.5/en/partitioning-maintenance.html.
URL: https://mariadb.com/kb/en/optimize-table/
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> HELP OPTIMIZE TABLE

5>.查看索引的使用

MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第36张
MariaDB [yinzhengjie]> SHOW VARIABLES LIKE 'userstat';    #查看索引的使用功能默认是关闭的
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| userstat      | OFF   |
+---------------+-------+
1 row in set (0.00sec)
MariaDB [yinzhengjie]> SET GLOBAL userstat=1;          #临时开启该功能,也可以在配置文件中永久定义其开启,前提是咱们知道它是一个服务器参数。
Query OK, 0 rows affected (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SHOW VARIABLES LIKE 'userstat';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| userstat      | ON    |
+---------------+-------+
1 row in set (0.00sec)
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> SET GLOBAL userstat=1;       #临时开启该功能,也可以在配置文件中永久定义其开启,它是服务器变量
MariaDB [yinzhengjie]>SHOW INDEX_STATISTICS;        #查看哪些索引被利用了,哪些没有被利用。
+--------------+--------------+------------+-----------+
| Table_schema | Table_name   | Index_name | Rows_read |
+--------------+--------------+------------+-----------+
| mysql        | tables_priv  | PRIMARY    |         1 |
| mysql        | columns_priv | PRIMARY    |         2 |
| yinzhengjie  | index_test   | PRIMARY    |         1 |
+--------------+--------------+------------+-----------+
3 rows in set (0.00sec)
MariaDB [yinzhengjie]> 

四.EXPLAIN

1>.EXPLAIN

通过EXPLAIN来分析索引的有效性
语法格式:EXPLAIN SELECT clause
  获取查询执行计划信息,用来查看查询优化器如何执行查询

2>.案例演示

MySQL/MariaDB数据库的索引工作原理和优化第7张MySQL/MariaDB数据库的索引工作原理和优化第38张
MariaDB [yinzhengjie]>HELP EXPLAIN
Name: 'EXPLAIN'
Description:
Syntax:
EXPLAIN [explain_type] SELECT select_options
explain_type:
    EXTENDED
  |PARTITIONS
Or:
EXPLAIN tbl_name
The EXPLAIN statement can be used either as a way to obtain information
about how MySQL executes a statement, or as a synonym forDESCRIBE:
o When you precede a SELECT statement with the keyword EXPLAIN, MySQL
  displays information from the optimizer about the query execution
  plan. That is, MySQL explains how it would process the statement,
  including information about how tables are joined and in whichorder.
  EXPLAIN EXTENDED can be used to obtain additional information.
  For information about using EXPLAIN and EXPLAIN EXTENDED to obtain
  query execution plan information, see
  https://mariadb.com/kb/en/explain/.

o EXPLAIN PARTITIONS is useful only when examining queries involving
  partitioned tables. For details, see
  http://dev.mysql.com/doc/refman/5.5/en/partitioning-info.html.

o EXPLAIN tbl_name is synonymous with DESCRIBE tbl_name or SHOW COLUMNS
  FROM tbl_name. For information about DESCRIBE and SHOW COLUMNS, see
  [HELP DESCRIBE], and [HELP SHOW COLUMNS].
URL: https://mariadb.com/kb/en/explain/

MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> 
MariaDB [yinzhengjie]> HELP EXPLAIN
MariaDB [yinzhengjie]> EXPLAIN SELECT * FROM index_test WHERE id = 99999;
+------+-------------+------------+-------+---------------+---------+---------+-------+------+-------+
| id   | select_type | table      | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+------+-------------+------------+-------+---------------+---------+---------+-------+------+-------+
|    1 | SIMPLE      | index_test | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
+------+-------------+------------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> EXPLAIN SELECT * FROM index_test WHERE age = 99999;
+------+-------------+------------+------+---------------+------+---------+------+-------+-------------+
| id   | select_type | table      | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+------+-------------+------------+------+---------------+------+---------+------+-------+-------------+
|    1 | SIMPLE      | index_test | ALL  | NULL          | NULL | NULL    | NULL | 99659 | Using where |
+------+-------------+------------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00sec)
MariaDB [yinzhengjie]> 

3>.EXPLLAIN输出信息说明

id: 
  当前查询语句中,每个SELECT语句的编号
    复杂类型的查询有三种:
      简单子查询
      用于FROM中的子查询
      联合查询:UNION(注意:UNION查询的分析结果会出现一个额外匿名临时表)
select_type:
  简单查询为SIMPLE
  复杂查询:
    SUBQUERY 简单子查询
    PRIMARY 最外面的SELECT
    DERIVED 用于FROM中的子查询
    UNION UNION语句的第一个之后的SELECT语句
    UNION RESULT 匿名临时表
table:
  SELECT语句关联到的表
type:
  关联类型或访问类型,即MySQL决定的如何去查询表中的行的方式,以下顺序,性能从低到高:
    ALL: 全表扫描
    index:根据索引的次序进行全表扫描;如果在Extra列出现“Using index”表示了使用覆盖索引,而非全表扫描
    range:有范围限制的根据索引实现范围扫描;扫描位置始于索引中的某一点,结束于另一点
    ref: 根据索引返回表中匹配某单个值的所有行
    eq_ref:仅返回一个行,但与需要额外与某个参考值做比较
    const, system: 直接返回单个行
possible_keys:
  查询可能会用到的索引
key: 
  查询中使用到的索引
key_len: 
  在索引使用的字节数
ref: 
  在利用key字段所表示的索引完成查询时所用的列或某常量值
rows:
  MySQL估计为找所有的目标行而需要读取的行数
Extra:
  额外信息
  Using index:MySQL将会使用覆盖索引,以避免访问表
  Using where:MySQL服务器将在存储引擎检索后,再进行一次过滤
  Using temporary:MySQL对结果排序时会使用临时表
  Using filesort:对结果使用一个外部索引排序
博主推荐阅读:
  https://dev.mysql.com/doc/refman/5.7/en/explain-output.html

免责声明:文章转载自《MySQL/MariaDB数据库的索引工作原理和优化》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用Docker 容器配置nexus3.29 私有仓库黑马lavarel教程---5、模型操作(AR模式)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

SQL Server 阻塞原因分析

这里通过连接在sysprocesses里字段值的组合来分析阻塞源头,可以把阻塞分为以下5种常见的类型(见表)。waittype,open_tran,status,都是sysprocesses里的值,“自我修复?”列的意思,就是指阻塞能不能自动消失。  5种常见的阻塞类型 类型 waittype open_tran status 自我修复 原因/其他特征...

利用select/poll监听多个设备详解

如果一个应用程序去处理多个设备,例如应用程序读取网路数据,按键,串口,一般能想到的有三种方法: 方法1:串行+阻塞的方式读取:while(1) { read(标准输入);read(网络);}缺点:每当阻塞读取标准输入时,如果用户不进行标准输入的操作,而此时客户端给服务器发送数据,导致服务器无法读取客户端发送来的数据! 方法2:采用多线程或者多进程机制来实现...

shell脚本应用练习(4)

一:正则表达式grep -a   不要忽略二进制数据。 -A  <显示列数> 除了显示符合范本样式的那一行之外,并显示该行之后的内容。 -b   在显示符合范本样式的那一行之外,并显示该行之前的内容。 -c   计算符合范本样式的列数。 -C  <显示列数>或-<显示列数>  除了显示符合范本样式的那一列之外,并显示该列...

SPEC CPU——简介和使用

前言 SPEC CPU是一套行业标准的CPU密集型基准测试套件。SPEC设计了此套件,以使用实际用户应用程序开发的工作负载,在最广泛的实际硬件范围内提供计算密集型性能的比较度量。这些基准作为源代码提供,要求用户习惯使用编译器命令以及通过控制台或命令提示窗口通过命令解释器使用的其他命令,以便生成可执行二进制文件。 SPEC CPU2006和SPEC CPU2...

MySQL Binlog详解

MySQL Binlog详解   Mysql的binlog日志作用是用来记录mysql内部增删改查等对mysql数据库有更新的内容的记录(对数据库的改动),对数据库的查询select或show等不会被binlog日志记录;主要用于数据库的主从复制以及增量恢复。 mysql的binlog日志必须打开log-bin功能才能生存binlog日志 -rw-rw-...

鸢尾花种类预测--数据集

1 案例:鸢尾花种类预测 Iris数据集是常用的分类实验数据集,由Fisher, 1936收集整理。Iris也称鸢尾花卉数据集,是一类多重变量分析的数据集。关于数据集的具体介绍: 2 scikit-learn中数据集介绍 2.1 scikit-learn数据集API介绍 sklearn.datasets 加载获取流行数据集 datasets.load_...