-
索引应用
1.1. 准备表
mysql> source /root/t100w.sql
1.2.设置用户权限
mysql> grant all on *.* to root@'10.0.0.%' identified by '123';
1.3压测
shell> mysqlslap --defaults-file=/etc/my.cnf --concurrency=50 --iterations=1 --create-schema='test' --query="select * from test.t100w where k2='780P'" engine=innodb --number-of-queries=1000 -uroot -p123 -h10.0.0.51 -verbose 参数: --concurrency=50 : 模拟同时100会话连接 --create-schema='test' : 操作的库是谁 --query="select * from test.t100w where k2='780P'" :做了什么操作 --number-of-queries=1000 : 一共做了多少次查询 mysqlslap: [Warning] Using a password on the command line interface can be insecure. Benchmark Running for engine rbose Average number of seconds to run all queries: 352.097 seconds Minimum number of seconds to run all queries: 352.097 seconds Maximum number of seconds to run all queries: 352.097 seconds Number of clients running queries: 50 Average number of queries per client: 20
-
查询表的索引
desc t100w; ----- Key ----- PK --> 主键(聚簇索引) MUL --> 辅助索引 UK --> 唯一索引 mysql> show index from t100w;
-
创建索引
3.1 单列辅助索引select * from test.t100w where k2='780P' 优化方式: 语法: alter table 表名 add index 索引名(列名); alter table t100w add index idx_k2(k2);
3.2 联合索引创建
mysql> alter table t100w add index idx_k1_num(k1,num);
3.3 前缀索引创建
判断前缀长度多少合适: select count(distinct(left(name,5))) from city ; select count(distinct name) from city ; 创建前缀索引 mysql> alter table city add index idx_n(name(5));
-
删除索引
alter table city drop index idx_n;
-
执行计划查看和分析
5.1 什么是执行计划?
优化器优化后的“执行方案”。5.2 作用 ?
a. 语句执行之前,通过执行计划,防患于未然。 b. 对于有性能问题的语句,进行分析。得出优化方案。
5.3 获取SQL的执行计划 。
mysql> desc select * from test.t100w where num=279106 and k2='VWtu'; +----+-------------+-------+------------+------+----------------+------+---------+-------------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+----------------+------+---------+-------------+------+----------+-------+ | 1 | SIMPLE | t100w | NULL | ref | ix_k2,idx,idx1 | idx1 | 22 | const,const | 1 | 100.00 | NULL | +----+-------------+-------+------------+------+----------------+------+---------+-------------+------+----------+-------+
5.4 执行计划介绍
table : 操作的表 type : 查询索引的类型(ALL、index、range、ref 、eq_ref、const(system)) possible_keys : 可能会走的。 key : 最终选择的索引。 key_len : 联合索引覆盖长度。 rows : 此次查询需要扫描的行数(预估值)。 Extra : 额外信息。
5.5 type 详解
5.5.1 ALL 全表扫描a. 查询条件没有建索引
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 | | NULL | | | dt | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | +-------+-----------+------+-----+-------------------+-----------------------------+ 5 rows in set (0.00 sec) mysql> desc select * from t100w where k2='780P'; +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+ | 1 | SIMPLE | t100w | NULL | ALL | NULL | NULL | NULL | NULL | 986679 | 10.00 | Using where | +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)
b. 有索引,但查询语句不能走。
mysql> alter table t100w add index idx(k2); mysql> desc select * from t100w where k2 like '%80P'; +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+ | 1 | SIMPLE | t100w | NULL | ALL | NULL | NULL | NULL | NULL | 986679 | 11.11 | Using where | +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+ mysql> desc select * from t100w where k2 != '780P'; +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+ | 1 | SIMPLE | t100w | NULL | ALL | idx | NULL | NULL | NULL | 986679 | 73.37 | Using where | mysql> desc select * from t100w where k2 not in ('780P'); +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+ | 1 | SIMPLE | t100w | NULL | ALL | idx | NULL | NULL | NULL | 986679 | 73.37 | Using where | +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
5.5.2 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 | 17 | NULL | 986679 | 100.00 | Using index | +----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+-------------+
5.5.3 range 索引范围扫描
mysql> desc select * from city where id<100; mysql> desc select * from city where countrycode like 'CH%'; mysql> desc select * from city where countrycode='CHN' or countrycode='USA'; mysql> desc select * from world.city where countrycode in ('CHN','USA'); union all 改写: desc select * from city where countrycode='CHN' union all select * from city where countrycode='USA'; 注意: 如果重复值过多的话,可能改写的效果不佳。 通过压测: 判断改写效果。 没改写的: mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from world.city where countrycode in ('CHN','USA'); " engine=innodb --number-of-queries=2000 -uroot -p123 -h10.0.0.51 -verbose 改写后的: mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city where countrycode='CHN' union all select * from city where countrycode='USA'; " engine=innodb --number-of-queries=2000 -uroot -p123 -h10.0.0.51 -verbose
5.5.4 ref : 辅助索引等值查询
mysql> desc select * from city where countrycode='CHN';
5.5.5 eq_ref:
非驱动表的连接条件是主键或唯一键。是多表连接中性能最好的查询方法。 where条件: mysql> desc select a.name,b.name 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 | range | CountryCode,idx | idx | 4 | NULL | 1 | 100.00 | Using index condition | | 1 | SIMPLE | b | NULL | eq_ref | PRIMARY | PRIMARY | 3 | world.a.CountryCode | 1 | 100.00 | NULL | +----+-------------+-------+------------+--------+-----------------+---------+---------+---------------------+------+----------+-----------------------+ 左外连接: mysql> desc select a.name,b.name from city as a left join country as b on a.countrycode=b.code; +----+-------------+-------+------------+--------+---------------+---------+---------+---------------------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+--------+---------------+---------+---------+---------------------+------+----------+-------+ | 1 | SIMPLE | a | NULL | ALL | NULL | NULL | NULL | NULL | 4188 | 100.00 | NULL | | 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)
5.5.6 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 | +----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
5.5.7 NULL
mysql> desc select * from city where id=1000000; +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+ | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | no matching row in const table | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
5.6. key_len 说明
5.6.0 计算方式a. 介绍: 索引的应用长度 b. 作用: 判断联合索引的覆盖长度。 idx(a,b,c) c. 如何计算key_len 总长度的计算: a+b+c d. 每个索引列占用多长? 每个列key_len,是这个列的《最大》预留长度 。 影响因素: 1. 数据类型 2. not null 3. 字符集(字符串类型) 数字类型: 最大长度 key_len(not null) key_len(not null) int 4 4 4+1 tinyint 1 1 1+1 字符串类型 (utf8): 最大长度 key_len(not null) key_len(not null) char(10) 30 30 30+1 varchar(10) 30+2 30+2 30+2+1 字符串类型 (utf8mb4): 最大长度 key_len(not null) key_len(not null) char(10) 40 40 40+1 varchar(10) 40+2 40+2 40+2+1 建表: create table test ( id int not null primary key auto_increment, a int not null , b char(10) not null , c char(5) , d varchar(20) not null )engine=innodb charset=utf8mb4; alter table test add index idx(a,b,c,d); 4+40+21+82=147 mysql> desc select * from test where a=1; +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | test | NULL | ref | idx | idx | 4 | const | 1 | 100.00 | Using index | +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) mysql> desc select * from test where a=1 and b='aa'; +----+-------------+-------+------------+------+---------------+------+---------+-------------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+-------------+------+----------+-------------+ | 1 | SIMPLE | test | NULL | ref | idx | idx | 44 | const,const | 1 | 100.00 | Using index | +----+-------------+-------+------------+------+---------------+------+---------+-------------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) mysql> desc select * from test where a=1 and b='aa' and c='aa' ; +----+-------------+-------+------------+------+---------------+------+---------+-------------------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+-------------------+------+----------+-------------+ | 1 | SIMPLE | test | NULL | ref | idx | idx | 65 | const,const,const | 1 | 100.00 | Using index | +----+-------------+-------+------------+------+---------------+------+---------+-------------------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) mysql> desc select * from test where a=1 and b='aa' and c='aa' and d='aa' ; +----+-------------+-------+------------+------+---------------+------+---------+-------------------------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+-------------------------+------+----------+-------------+ | 1 | SIMPLE | test | NULL | ref | idx | idx | 147 | const,const,const,const | 1 | 100.00 | Using index | +----+-------------+-------+------------+------+---------------+------+---------+-------------------------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)
5.6.1 联合索引应用细节
a. 联合索引全覆盖
idx(num,k1,k2) mysql> desc select * from t100w where num=641631 and k1='At' and k2='rsEF'; mysql> desc select * from t100w where k1='At' and num=641631 and k2='rsEF';
b. 部分覆盖
mysql> desc select * from t100w where num=641631 and k1='At' ; mysql> desc select * from t100w where k1='At' and num=641631 ; mysql> desc select * from t100w where num=641631 and k2 like 'rsE%';
c. 完全不覆盖
mysql> desc select * from t100w where k1='At' and k2 like 'rsE%';
d. 在多子句 必须得使用联合索引
where a order by b where a group by b order by xxx
5.7 Extra
using where : 此次查询中有部分条件是没有走索引的。 如果出现以上信息,说明where 条件,索引设计问题或者语句有问题。 using filesort : 出现文件排序,order by 、 group by 、 distinct ...
MySQL索引及执行计划
最新推荐文章于 2021-04-19 12:07:12 发布