为什么80%的码农都做不了架构师?>>>   

这里所谈论只针对B-Tree类型索引,也是MySQL用的最多最普通的索引。创建索引的时候是按照字面量的顺序创建的,这个要特别注意。在B-Tree类型索引中,索引顺序是至关重要的。

高性能索引

  • 索引要小而美

  • 单列索引

  • 前缀索引

  • 多列索引

  • 选择合适的索引顺序

  • 覆盖索引

  • 使用索引扫描来排序

首先构造1亿条数据

参照前面写的文章造数据

http://blog.csdn.net/csujiangyu/article/details/51096978

索引结构如下

mysql> show index from user;
+-------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name                | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user  |          0 | PRIMARY                 |            1 | id          | A         |    92123632 |     NULL | NULL   |      | BTREE      |         |               |
| user  |          1 | idx_last_first_name_age |            1 | last_name   | A         |      363474 |     NULL | NULL   | YES  | BTREE      |         |               |
| user  |          1 | idx_last_first_name_age |            2 | first_name  | A         |    92123840 |     NULL | NULL   | YES  | BTREE      |         |               |
| user  |          1 | idx_last_first_name_age |            3 | age         | A         |    87360984 |     NULL | NULL   | YES  | BTREE      |         |               |
| user  |          1 | idx_phone               |            1 | phone       | A         |    92123840 |     NULL | NULL   | YES  | BTREE      |         |               |
| user  |          1 | idx_create_time         |            1 | create_time | A         |       88503 |     NULL | NULL   | YES  | BTREE      |         |               |
+-------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
6 rows in set (0.00 sec)

user表一共有4个索引,包括一个主键id,2个单列索引(phone, create_time), 1个多列索引(last_name+first_name+age)

通过explain来查看使用索引情况

主要关注如下:

  • type:访问类型,性能从差到好为:

    ALL -> index -> range -> ref -> eq_ref -> const,system -> NULL

  • index:使用的索引

可以使用索引的情况

单列索引全值匹配

这是最简单的方式

mysql> explain SELECT * from user where phone = '13901986429';
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | user  | NULL       | ref  | idx_phone     | idx_phone | 14      | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.01 sec)

从type可以得知访问类型ref,使用索引key为idx_phone。

多列索引全值匹配

mysql> explain SELECT * FROM  user where last_name='last_name_110' and first_name='first_name_115' and sex='F';
+----+-------------+-------+------------+------+-------------------------+-------------------------+---------+-------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys           | key                     | key_len | ref         | rows | filtered | Extra       |
+----+-------------+-------+------------+------+-------------------------+-------------------------+---------+-------------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ref  | idx_last_first_name_age | idx_last_first_name_age | 96      | const,const |    1 |    10.00 | Using where |
+----+-------------+-------+------------+------+-------------------------+-------------------------+---------+-------------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

前缀索引

如果是单列索引,可以匹配列的最左前缀

mysql> explain SELECT * from user where phone like '139019864%';
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | user  | NULL       | range | idx_phone     | idx_phone | 14      | NULL |  100 |   100.00 | Using index condition |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.01 sec)

如果是多列索引,可以从左开始组合索引

mysql> explain SELECT * FROM  user where last_name='last_name_110' and first_name='first_name_115';
+----+-------------+-------+------------+------+-------------------------+-------------------------+---------+-------------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys           | key                     | key_len | ref         | rows | filtered | Extra |
+----+-------------+-------+------------+------+-------------------------+-------------------------+---------+-------------+------+----------+-------+
|  1 | SIMPLE      | user  | NULL       | ref  | idx_last_first_name_age | idx_last_first_name_age | 96      | const,const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+-------------------------+-------------------------+---------+-------------+------+----------+-------+
1 row in set, 1 warning (0.01 sec)

匹配索引值的范围

使用between

mysql> explain select * from user where id between 1 and 10;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |   10 |   100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

使用in

mysql> explain select * from user where id in (1, 2, 3);
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |    3 |   100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)

使用or

mysql> explain select * from user where id=1 or id=10;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | range | PRIMARY       | PRIMARY | 4       | NULL |    2 |   100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

覆盖索引

Extra字段为Using index,可以看出返回数据只需要查索引即可,不需要回表查其他字段数据。

mysql> explain select phone from user where phone='13900123456';
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ref  | idx_phone     | idx_phone | 14      | const |    1 |   100.00 | Using index |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

不能使用索引的情况

从type为ALL可以看出进行了全表扫描。

没有使用左前缀索引

phone是索引列,格式为’%XXX’不能是使用索引

mysql> explain SELECT * from user where phone like '%39019864%';
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows    | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9698255 |    11.11 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

没有采用最左组合索引

last_name + first_name + sex联合组成了多列索引,采用最左匹配, 只有last_name,last_name + first_name,last_name + first_name + sex才能使用索引。

mysql> explain SELECT * FROM  user where first_name='first_name_115' and sex='F';
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows    | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9698255 |     1.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

使用函数

mysql> explain SELECT * FROM  user where left(phone, 11) = '13900123456';
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows    | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9698255 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

用索引字段进行计算

mysql> explain select * from user where id + 1 = 2;
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows     | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 92123838 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

or后面没有使用索引

mysql> explain select * from user where id=1 or age=10;
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows     | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | PRIMARY       | NULL | NULL    | NULL | 92123838 |    10.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

索引和数据占用空间的查询

-- 查看example数据库整体大小
SELECT CONCAT(table_schema,'.',table_name) AS 'Table Name', CONCAT(ROUND(table_rows/1000000,4),'M') AS 'Number of Rows', CONCAT(ROUND(data_length/(1024*1024*1024),4),'G') AS 'Data Size', CONCAT(ROUND(index_length/(1024*1024*1024),4),'G') AS 'Index Size', CONCAT(ROUND((data_length+index_length)/(1024*1024*1024),4),'G') AS'Total'FROM information_schema.TABLES WHERE table_schema = 'example';

从图可以看出,1亿条数据索引占用了9.69G,数据占用了10G,总共占用了将近20G。索引占用空间几乎和数据大小一样,因此我们需要慎用索引,在必要的情况下才使用,索引要小而美。

转载于:https://my.oschina.net/boltwu/blog/726790

MySQL索引的学习和研究相关推荐

  1. MYSQL索引结构学习笔记

    mysql 的数据.索引.DDL 等数据,都是以文件形式存储的, 所以导致每次查询都是一次I/O操作,当I/O操作过大时,会严重影响效率 MYSQL索引结构: mysql使用的是B+树来存储索引的,为 ...

  2. MySQL索引知识点学习

    什么是索引? MySQL官方对索引的定义为:索引是帮助MySQL高效获取数据的数据结构.通俗的说,索引就相当于一本书的目录,能加快数据库的查询速度. 一般来说索引本身也很大,不可能全部存储在内存中,因 ...

  3. mysql索引实例_mysql索引之十:Mysql 索引案例学习

    理解索引最好的办法是结合示例,所以这里准备了一个索引的案例. 假设要设计一个在线约会网站,用户信息表有很多列,包裹国家,地区,城市,性别,眼睛颜色,等等.完整必须支持上面这些特征的各种组合来搜索用户, ...

  4. Mysql 索引案例学习

    理解索引最好的办法是结合示例,所以这里准备了一个索引的案例. 假设要设计一个在线约会网站,用户信息表有很多列,包裹国家,地区,城市,性别,眼睛颜色,等等.完整必须支持上面这些特征的各种组合来搜索用户, ...

  5. MySQL索引的理解学习,面试不问索引原理就是事务原理

    目录 MySQL执行SQL的整体流程 引言, MySQL索引底层学习原因 磁盘介绍(理解磁盘IO) 索引底层数据结构B+树 B+树(聚集索引) B+树(辅助索引) 思考一下为何使用B+树结构, 不是B ...

  6. mysql索引linke和等于_MySQL索引的学习

    MySQL索引的学习 关于使用mysql索引的好处,合理的设计并使用mysql索引能够有效地提高查询效率.对于没有索引的表,单表查询可能几十万数据就是平静,在大型网站单日可能会产生几十万甚至几百万的数 ...

  7. MySQL 索引学习笔记

    MySQL 索引学习笔记 索引基本概念 索引优点 B-Tree 索引 基本原理 使用场景 使用限制 哈希索引 基本原理 使用限制 自适应哈希索引 处理哈希冲突 相关面试题 高性能索引策略 独立的列 前 ...

  8. php 如何设计索引_Mysql学习浅谈mysql的索引设计原则以及常见索引的区别

    <Mysql学习浅谈mysql的索引设计原则以及常见索引的区别>要点: 本文介绍了Mysql学习浅谈mysql的索引设计原则以及常见索引的区别,希望对您有用.如果有疑问,可以联系我们. 索 ...

  9. mysql的学习要点_MySQL中的联合索引的学习要点总结

    MySQL中的联合索引的学习要点总结 联合索引又叫复合索引.对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分.例如索引是key index (a ...

最新文章

  1. 为什么以太坊能成为区块链2.0的代表之作?
  2. 使用sn.exe为程序集签名
  3. [Qt教程] 第28篇 XML(二)使用DOM创建和操作XML文档
  4. python做一副54扑克牌发牌技巧_德州扑克讲堂:高级技巧 胜率之摊牌胜率的算法...
  5. An impassioned circulation of affection(尺取+预处理)
  6. Twisted入门教程(9)
  7. 可视化Python编译软件:GUI2Exe
  8. 国赛助力:第三类边界条件热传导方程及基于三对角矩阵的数值计算MATLAB实现(2020A)
  9. jQ UI 后台管理系统基础UI
  10. Prometheus客户端docker监控cAdvisor
  11. HPET(High Precision Event Timer)简要说明
  12. [CSP-S 2022] 策略游戏
  13. 【历史上的今天】10 月 26 日:NetBSD 系统发布;Windows 8 诞生;微软推出 Surface 系列
  14. H264编码器5( x264源代码简单分析:x264_slice_write() 与H264 编码简介)
  15. 触摸屏基本原理介绍【转】
  16. BOM的增删改及复制
  17. SegmentFault 讲堂一周岁:Keep learning
  18. 八、串,数组和广义表
  19. Word VBA自动排版(6)- 专利撰写生成权利要求模板
  20. Jeecg 模糊查询 怎么用!

热门文章

  1. WayOS路由智能小区组网方案
  2. 大数据时代云计算在新媒体平台的应用研究
  3. Docker 镜像小结 - 每天5分钟玩转 Docker 容器技术(21)
  4. Yii 2 —— Model表前缀
  5. Nginx中worker_connections的问题
  6. DIY一个DNS查询器:了解DNS协议
  7. day01_Loadrunner基础流程
  8. 从CTO到创始人 孙元浩基础软件破局之路
  9. jQuery动画---自定义动画animate()
  10. 【UE】常用的UltraEdit使用技巧