Linux操作文档——MySQL索引及执行计划(5.7.26)

文章目录

    • 一、索引
      • 1、索引的分类
      • 2、Btree索引功能上的分类
    • 二、索引的命令
      • 1、查询索引
      • 2、创建索引
    • 三、执行计划分析
      • 1、作用
      • 2、获取执行计划
      • 3、参数说明
        • 1、table
        • 2、type
        • 3、possible_key
        • 4、key
        • 5、key_len 索引长度
        • 6、Extra 额外的信息说明
    • 四、压力测试
      • 1、创建测试数据
      • 2、查看数据情况
      • 3、未优化前压力测试
      • 4、创建索引
      • 5、优化后压力测试


一、索引

1、索引的分类

分类 说明
(BTREE)B树 将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依次遍历node,获取leaf。这是MySQL里默认和最常用的索引类型
(RTREE)R树 在MySQL很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。相对于BTREE,RTREE的优势在于范围查找
Hash 可以一次定位,不需要像树形索引那样逐层查找,但是,这种高效只在“=”和“in”条件下高效,对于范围查询、排序及组合索引仍然效率不高
FULLTEXT 全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引
GIS 索引 InnoDB支持空间索引,通过R树来实现,使得空间搜索变得高效。 InnoDB空间索引也支持MyISAM引擎现有的空间索引的语法,此外,InnoDB空间索引支持完整的事务特性以及隔离级别

2、Btree索引功能上的分类

索引类别 辅助索引 聚集索引 联合索引
说明 提取索引列的所有值,进行排序;将排好序的值,均匀的存放在叶子节点,进一步生成枝节点和根节点;在叶子节点中的值,都会对应存储主键ID MySQL 会自动选择主键作为聚集索引列,没有主键会选择唯一键,如果都没有会生成隐藏的;MySQL进行存储数据时,会按照聚集索引列值得顺序,有序存储数据行; 聚集索引直接将原表数据页,作为叶子节点,然后提取聚集索引列向上生成枝和根 指对表上的多个列进行索引
区别 表中任何一个列都可以创建辅助索引,在你有需要的时候,只要名字不同即可;辅助索引,叶子节点只存储索引列的有序值+聚集索引列值 在一张表中,聚集索引只能有一个,一般是主键;聚集索引,叶子节点存储的时有序的整行数据;MySQL 的表数据存储是聚集索引组织表 最左匹配原则:按照联合索引的顺序,从前往后依次使用生效,如果中间某个索引没有使用,那么断点前面的索引部分起作用,断点后面的索引没有起作用

二、索引的命令

1、查询索引

参数 说明
PRI 主键索引
MUL 辅助索引
UNI 唯一索引
mysql> use world;
Database changed
mysql> desc city;
+-------------+----------+------+-----+---------+----------------+
| Field       | Type     | Null | Key | Default | Extra          |
+-------------+----------+------+-----+---------+----------------+
| ID          | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name        | char(35) | NO   |     |         |                |
| CountryCode | char(3)  | NO   | MUL |         |                |
| District    | char(20) | NO   |     |         |                |
| Population  | int(11)  | NO   |     | 0       |                |
+-------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

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         |        4046 |     NULL | NULL   |      | BTREE      |         |               |
| city  |          1 | CountryCode |            1 | CountryCode | A         |         232 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)

2、创建索引

1、单列的辅助索引

mysql> alter table city add index idx_name(name);

2、多列的联合索引

mysql> alter table city add index idx_c_p(countrycode,population);

3、唯一索引

mysql> alter table city add unique index uidx_dis(district);

4、前缀索引

mysql> alter table city add index idx_dis(district(5));

5、删除索引

mysql> alter table city drop index idx_name;

三、执行计划分析

1、作用

将优化器选择后的执行计划截取出来,便于管理管判断语句得执行效率。

2、获取执行计划

mysql> desc select * from test.t_100w where k2='MN89';
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+-------------+
|  1 | SIMPLE      | t_100w | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 997246 |    10.00 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.03 sec)

3、参数说明

1、table

表名

2、type

含义 性能 补充
NULL 无数据
const(system) 主键或者唯一键的等值查询 != 和not in等语句走range
eq_ref 多表连接时,子表使用主键列或唯一列作为连接条件
ref 辅助索引等值查询 包括带有union,union all[^1]的查询语句
range 索引范围扫描 > < >= <= , between and ,or,in,like
index 全索引扫描
ALL 全表扫描 !=(不等于)和not in等不等值语句不走索引
[^1]: union:合并两个或多个SELECT 语句的结果集,并对结果去重且排序;union all允许重复

3、possible_key

指出MySQL能使用哪些索引来优化查询,查询所涉及的列上的索引都会被列出,但不一定会被使用

4、key

查询优化器优化查询实际所使用的索引,如果没有可用的索引,则显示为NULL,如查询使用了覆盖索引,则该索引仅出现在Key列中

5、key_len 索引长度

表示索引字段的最大可能长度,KEY_LEN的长度由字段定义计算而来,并非数据的实际长度,字符长度取决于中文所占字节长度,utf8mb4为4字节,utf8为3字节。
例如varchar(20) utf8mb4
1、能存20个任意字符
2、不管存储的时字符、数字、中文,都1个字符最大预留长度是4个字节
3、对于中文,1个占4个字节
4、对于数字和字母,1个实际占用大小是1个字节
索引长度计算(ken_len越长,说明索引使用的越充分)

类型 计算方法(utf8mb4环境下)
int int最长4字节+非空1字节=5字节
char ()中数字乘4+非空1字节
varchar 开始1字节+()中数字乘4+非空1字节+结束1字节
联合索引覆盖长度=所应用索引长度相加

6、Extra 额外的信息说明

Using filesort:在查询中有关排序的条件列没有合理的应用索引,多见于order by、group by、distinct、 union

四、压力测试

1、创建测试数据

[root@mysql-1 ~]# mysql -uroot -p1
mysql> create database test charset utf8mb4 collate utf8mb4_bin;
Query OK, 1 row affected (0.00 sec)

mysql> use test;
Database changed
mysql> create table t100w (id int,num int,k1 char(2),k2 char(4),dt timestamp);
Query OK, 0 rows affected (0.01 sec)

mysql> delimiter //
mysql> create  procedure rand_data(in num int)
    -> begin
    -> declare str char(62) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    -> declare str2 char(2);
    -> declare str4 char(4);
    -> declare i int default 0;
    -> while i<num do
    -> set str2=concat(substring(str,1+floor(rand()*61),1),substring(str,1+floor(rand()*61),1));
    -> set str4=concat(substring(str,1+floor(rand()*61),2),substring(str,1+floor(rand()*61),2));
    -> set i=i+1;
    -> insert into t100w values (i,floor(rand()*num),str2,str4,now());
    -> end while;
    -> end;
    -> //
Query OK, 0 rows affected (0.01 sec)

mysql> delimiter ;
ysql> call rand_data(1000000);
Query OK, 1 row affected (3 min 50.61 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

2、查看数据情况

mysql> select count(*) from t100w;
+----------+
| count(*) |
+----------+
|  1000000 |
+----------+
1 row in set (0.24 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)

3、未优化前压力测试

[root@mysql-1 ~]# mysqlslap --defaults-file=/etc/my.cnf \
--concurrency=100 --iterations=1 --create-schema='test' \
--query="select * from test.t100w where k2='6734'" engine=innodb \
--number-of-queries=2000 -uroot -p1 -verbose
mysqlslap: [Warning] Using a password on the command line interface can be insecure.
Benchmark
	Running for engine rbose     //运行引擎rbose
	Average number of seconds to run all queries: 395.284 seconds     //运行查询的平均秒数
	Minimum number of seconds to run all queries: 395.284 seconds     //运行查询的最小秒数
	Maximum number of seconds to run all queries: 395.284 seconds     //运行查询的最大秒数
	Number of clients running queries: 100     //运行查询的客户机数量
	Average number of queries per client: 20     //每个客户机的平均查询数
参数 说明
–concurrency 表示并发量,也就是模拟多少个客户端同时执行query
–iterations 测试执行的迭代次数,代表要在不同的并发环境中,各自运行测试多少次
–create-schema 代表自定义的测试库名称
–query 使用自定义脚本或语句执行测试
engine 代表要测试的引擎
–number-of-queries 总的测试查询次数(并发客户数×每客户查询次数)
-verbose 日志输出

4、创建索引

[root@mysql-1 ~]# mysql -uroot -p1
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> alter table t100w add index idx_k2(k2);
Query OK, 0 rows affected (1.46 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> exit

5、优化后压力测试

[root@mysql-1 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='test' --query="select * from test.t100w where k2='6734'" engine=innodb --number-of-queries=2000 -uroot -p1 -verbose
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: 0.803 seconds
	Minimum number of seconds to run all queries: 0.803 seconds
	Maximum number of seconds to run all queries: 0.803 seconds
	Number of clients running queries: 100
	Average number of queries per client: 20

你可能感兴趣的:(数据库,mysql)