DBA之路 6_MySQL_索引(下)及执行计划

1.1索引

MUL   辅助索引
PRI   主键(聚集索引)
UNI   唯一键
1.2索引的操作管理
建立 索引
mysql> alter table t100w add index idx_k2(k2);
Query OK, 0 rows affected (6.11 sec)
查询索引
mysql> show index from t100w;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t100w |          1 | idx_k2   |            1 | k2          | A         |        3826 |     NULL | NULL   | YES  | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

mysql> desc t100w;
+-------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type      | Null | Key | Default           | Extra                       |
+-------+-----------+------+-----+-------------------+-----------------------------+
| id    | int(11)   | YES  |     | NULL              |                             |
| num   | int(11)   | YES  |     | NULL              |                             |
| k1    | char(2)   | YES  |     | NULL              |                             |
| k2    | char(4)   | YES  | MUL | NULL              |                             |
| dt    | timestamp | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------+-----------+------+-----+-------------------+-----------------------------+
5 rows in set (0.00 sec)
创建唯一索引
mysql>alter table t100w add unique index index_k1(k1);

前缀索引只能设置给字符串类型的列
mysql> alter table city add index idx_name(name(3));
Query OK, 0 rows affected (0.10 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table city drop index idx_name;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0
;

创建联合索引
mysql> alter table city add index idx_n_p(countrycode,population);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from city
    -> ;
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| city  |          0 | PRIMARY     |            1 | ID          | A         |        4188 |     NULL | NULL   |      | BTREE      |         |               |
| city  |          1 | CountryCode |            1 | CountryCode | A         |         232 |     NULL | NULL   |      | BTREE      |         |               |
| city  |          1 | idx_n_p     |            1 | CountryCode | A         |         232 |     NULL | NULL   |      | BTREE      |         |               |
| city  |          1 | idx_n_p     |            2 | Population  | A         |        4052 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (0.00 sec)

2.执行计划

2.1作用

上线新的查询语句之前,进行提前预警性能较差的语句(提前预估语句性能)
在出现性能问题时可以找到合理的解决思路

2.2执行计划获取

desc和explain都可以获取执行计划(部分),结果一样
mysql> desc select * from city where name='ShangHai';
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | city  | NULL       | ref  | idx_name      | idx_name | 35      | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

重要的列:
table:        显示从哪个表查询,单表无所谓,多表会有作用
type:          索引的应用级别(应用类型)
possible_key   可能会使用到的索引
key            实际用到的索引
key_len        联合索引的覆盖程度(针对联合索引,可以判断出用的索引)
rows           覆盖的行数(查询的行数,越少越好)
Extra          额外的信息

2.3关键信息介绍

type:ref
级别
1>ALL:全表扫描,遍历,不走索引
出现ALL的情况:(1)没建立索引
              (2)建了索引不走
2>Index:全索引扫描
3>range:索引范围扫描
4>ref:辅助索引等值查询
5>eq_ref:多表连接查询时,on的条件列是唯一索引或主键
6>const,system:主键或唯一键的等值查询
级别:从上往下,性能依次变好
ALL:全表扫描,遍历,不走索引
出现ALL的情况:(1)没建立索引
              (2)建了索引不走
六种不走索引的情况:
mysql> desc select * from t100w where k2 != 'aaa';            辅助索引出现!=才会出现all
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | t100w | NULL       | ALL  | idx_k2        | NULL | NULL    | NULL | 888567 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> desc select * from t100w where k2 like '%xy%';
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | t100w | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 888567 |    11.11 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> desc select k1 from t100w;
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------+
|  1 | SIMPLE      | t100w | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 888567 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> desc select * from t100w;
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------+
|  1 | SIMPLE      | t100w | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 888567 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------+
1 row in set, 1 warning (0.00 sec)

总结:(1) select * from 不会走索引
     (2)select 非索引列 from 不会走索引
     (3)!=不等于在辅助索引时是all在聚集索引是range
     (4)%a   模糊匹配在前时是ALL,在后面的时候会显示range
Index:全索引扫描
mysql> desc select k2 from t100w;
+----+-------------+-------+------------+-------+---------------+--------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key    | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+--------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | t100w | NULL       | index | NULL          | idx_k2 | 17      | NULL | 888567 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+--------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

取索引列的所有数据
range:索引范围扫描
辅助索引:<  >  <=  >=   like 这类可以接受
in   or   这类尽量避免
主键:!=   出现在主键列则会走range

mysql> desc select * from world.city where countrycode like 'C%'
mysql> desc select * from world.city where id!=3000;
mysql> desc select * from world.city where id>3000;

mysql> desc select * from world.city where countrycode in ('CHN','USA');

改写为:
desc
select * from world.city where countrycode='CHN'
union all 
select * from world.city where countrycode='USA';

ref:辅助索引等值查询
mysql> desc select * from city where countrycode='CHN';
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | city  | NULL       | ref  | CountryCode   | CountryCode | 3       | const |  363 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
eq_ref:多表连接查询时,on的条件列是唯一索引或主键
mysql> desc select a.name,b.name ,b.surfacearea 
    -> from city as a 
    -> join country as b 
    -> on a.countrycode=b.code 
    -> where a.population <100;
+----+-------------+-------+------------+--------+---------------+---------+---------+---------------------+------+----------+-------------+
| id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref                 | rows | filtered | Extra       |
+----+-------------+-------+------------+--------+---------------+---------+---------+---------------------+------+----------+-------------+
|  1 | SIMPLE      | a     | NULL       | ALL    | CountryCode   | NULL    | NULL    | NULL                | 4188 |    33.33 | Using where |
|  1 | SIMPLE      | b     | NULL       | eq_ref | PRIMARY       | PRIMARY | 3       | world.a.CountryCode |    1 |   100.00 | NULL        |
+----+-------------+-------+------------+--------+---------------+---------+---------+---------------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)
const,system:主键或唯一键的等值查询
mysql> desc select * from city where id='10';
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | city  | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

Extra:Null 额外的信息

+---------------------------------------+
| Extra                                 |
+---------------------------------------+
| Using index condition; Using filesort |
+---------------------------------------+
Using filesort解决方法:
mysql> desc select * from city where countrycode='CHN' order by population;
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra                                 |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+
|  1 | SIMPLE      | city  | NULL       | ref  | CountryCode   | CountryCode | 3       | const |  363 |   100.00 | Using index condition; Using filesort |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+---------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> alter table city add index idx_pop_cou(countrycode,population);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> desc select * from city where countrycode='CHN' order by population;
+----+-------------+-------+------------+------+-------------------------+-------------+---------+-------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys           | key         | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+-------------------------+-------------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | city  | NULL       | ref  | CountryCode,idx_pop_cou | idx_pop_cou | 3       | const |  363 |   100.00 | Using index condition |
+----+-------------+-------+------------+------+-------------------------+-------------+---------+-------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)


设置联合索引

3.Explain(desc)使用场景(面试题)

1.MySQL出现性能问题,总结有两种情况

(1)应急性的慢,突然夯住
应急处理:数据库夯住(卡了,资源耗尽)
处理过程:
1.show proesslist;获取到导致数据库夯住的语句
2.explain分析SQL语句的执行计划,有没有走索引,索引的类型情况
3.建索引,改语句
(2)一段时间慢(持续性)
1.记录慢日志,slowlog,分析slowlog
2.explain,分析SQL的执行计划,有没有走索引,索引的类型情况
3.建索引,改语句

4.索引应用规范

业务
1.产品的功能
2.用户的行为
“热”查询语句--->较慢--->slowlog
“热数据”

4.1建立索引的原则(DBA运维规范)

4.1.0说明
为了使索引的使用效率更高,在创建索引时,必须考虑在哪些字段上创建索引和创建什么类型的索引。那么索引设计原则又是怎样的?
4.1.1(必须的) 建表时一定要有主键,一般是个无关列

略.回顾一下,聚集索引结构.

4.1.2选择唯一性索引

唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。
4.1.3
当有where group by order by 时,要建立联合索引
4.10*********关于联合索引************
(1)where A, group by B. order by c ---------->(A,,B,C)
(2)只有where A B C
   1>都是等值的情况下(5.5版本以后无关索引顺序,都可以走索引),
但是,我们需要把唯一值最多的一列放到最左边
   2>如果有不等值的查询,例如以下情况
    select where A= and B> and C=
    索引顺序是ACB/CAB,语句改写为ACB/CAB,AC的位置取决于里面的唯一值的多少

你可能感兴趣的:(DBA之路 6_MySQL_索引(下)及执行计划)