mysql中一张表支持多个索引,但是在写SQL语句的时候,并没有主动指定使用哪个索引。
1、删除历史数据和新增数据的场景,检查索引使用情况
set long_query_time=0
:慢查询日志的阈值设置为0,表示这个线程接下来的语句都会记录到慢查询日志中
select * from t where a between 10000 and 20000; /*Q1*/
:默认使用索引进行查询
select * from t force index(a) where a between 10000 and 20000;/*Q2*/
:使用强制索引a进行查询
show index from t;
:show index 方法,看到一个索引的基数。 这个基数越大,索引的区分度越好。
analyze table t
:重新统计索引表
2、优化器的逻辑
优化器的逻辑:选择索引。
优化器的判断标准:扫描行数、是否使用临时表、是否排序等因素。
优化器选择索引的目的:找到一个最优的执行方案,并用最小的代价去执行语句。比如,在数据库里面,扫描行数是影响执行代价的因素之一。
基数:一个索引上不同的值得个数,使用命令show index
方法,看到一个索引的基数。
采样统计的时候,InnoDB 默认会选择 N 个数据页,统计这些页面上的不同值,得到一个平均值,然后乘以这个索引的页面数,就得到了这个索引的基数。
在 MySQL 中,有两种存储索引统计的方式,可以通过设置参数 innodb_stats_persistent 的值来选择:
- 设置为 on 的时候,表示统计信息会持久化存储。这时,默认的 N 是 20,M 是 10。
- 设置为 off 的时候,表示统计信息只存储在内存中。这时,默认的 N 是 8,M 是 16。
--创建表,表里面有2个字段,并分别创建上索引
CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`),
KEY `b` (`b`)
) ENGINE=InnoDB;
-存储过程用来插入10万行数据
delimiter ;;
create procedure idata()
begin
declare i int;
set i=1;
while(i<=100000)do
insert into t values(i, i, i);
set i=i+1;
end while;
end;;
delimiter ;
call idata();
--分析sql执行,使用索引a
mysql> explain select * from t where a between 10000 and 20000;
网友评论