第八章 MySQL的索引介绍

一、explain详解

1.explain语法

mysql> explain select * from user where age='30' and money > '1000000' and look='beautiful';
#1.查看中国和美国的城市人口数量
mysql> select name,population from city where countrycode='CHN' or countrycode='USA';

mysql> select name,population from city where countrycode in ('CHN','USA');

mysql> select name,population from city where countrycode='CHN' union all select name,population from city where countrycode='USA';

#2.查看三个命令的执行计划
mysql> explain select name,population from city where countrycode='CHN' or countrycode='USA';

mysql> explain select name,population from city where countrycode in ('CHN','USA');

mysql> explain select name,population from city where countrycode='CHN' union all select name,population from city where countrycode='USA';

#3.查询结果注释
id					#执行顺序
table				#查询的表
type				#查询使用的类型
possible_keys		 #可能使用的索引列
key					#真正实用的索引列
key_len				#索引长度,前缀索引的长度
ref					#查询级别是否达到ref级别
rows				#查询数据的数量
Extra
	Using temporary
	Using filesort 			#使用了默认的文件排序(如果使用了索引,会避免这类排序)order by
	Using join buffer		#使用了 join on
	Using index condition	#使用了索引

2.group by扩展

#1.插入一个表
mysql> create table jixiao(id int,name varchar(10),money int,product varchar(10));

#2.插入数据
mysql> insert into jixiao values('1','邱导','100000','汽车'),('2','laocai','80000','汽车'),('3','dawei','700000','房地产'),('4','laozhao','800000','房地产');

#3.查询不同行业总绩效
mysql> select sum(money),product from jixiao group by product;
+------------+-----------+
| sum(money) | product   |
+------------+-----------+
|    1500000 | 房地产    |
|     180000 | 汽车      |
+------------+-----------+
2 rows in set (0.00 sec)

#4.查询不同行业绩效最高的那个人

3.查询数据的方式

1)全表扫描

#1.什么是全表扫描?
	读取整个表的数据,使用explain语句查询执行计划中,type列的值是ALL
	
#2.什么时候使用全表扫描
	1)查询表中所有数据的时候
	mysql> explain select * from city;
	2)没有走索引的时候
	mysql> explain select name,population from city where population='92020';

2)索引扫描

#从上到下查询速度依次越来越快
1.index			#全索引扫描
	mysql> explain select name from city;

2.range			#范围查询使用该级别,但是当查询数据量过大的时候不走索引
	mysql> explain select name,population from city where countrycode='CHN' or countrycode='USA';
	mysql> explain select name,population from city where population > 3000000;
	
3.ref			#使用精确查询
	mysql> explain select name,population from city where countrycode='CHN';

4.eq_ref		#使用join on时可能出现该级别
	mysql> explain select city.name,city.population,country.name from country join city on city.countrycode=country.code where city.population < 100;

5.const			#当查询条件是主键或者唯一键的时候
	mysql> explain select * from city where id='1';

6.system		#跟const平级,当查询的数据所在表数据量很小的时候,并且查询条件使用主键或者唯一键

7.null			#当不用读取数据库数据的时候
	mysql> explain select max(population) from city;

二、索引的建立

1.建立索引的原则

1.如果可以建立唯一键索引,就建立唯一键索引
2.为经常需要排序、分组和联合操作的字段建立索引
3.为常作为查询条件的字段建立索引

4.尽量使用前缀索引
	如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT和BLOG类型的字段,进行全文检索
会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度

5.限制索引的数目
	索引的数目不是越多越好。每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。
修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。

6.删除不再使用或者很少使用的索引
	表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。数据库管理
员应当定期找出这些索引,将它们删除,从而减少索引对更新操作的影响。

2.不走索引的情况总结

1)没有查询条件,或者查询条件没有索引

#查询所有数据
mysql> explain select * from city;

#删除索引,然后查询
mysql> alter table city drop index District_key;
mysql> explain select * from city where District='heilongjiang';

2)查询结果集是原表中的大部分数据,应该是15%以上

#表中数据一共4079,查询数据539条,走索引    13.2%
mysql> explain select * from city where population > 500000;

#表中数据一共4079,查询数据737条,不走索引	18%
mysql> explain select * from city where population > 400000;

3)索引坏了

反复插入删除容易损坏索引

4)查询条件使用了运算符号

#运算符号如果在等号左边,则不走索引
mysql> explain select * from city where id-1=2;

#运算符号如果在等号右边,则走索引
mysql> explain select * from city where id=2+1;

5)隐式转换

# 1.建表
mysql> create table phone(id int,name varchar(10),number varchar(20));

#2.建立索引
mysql> alter table phone add unique key uni_key(number);

#3.插入数据
mysql> insert phone values(1,'警察局',110),(2,'消防',119),(3,'医院',120);

#4.测试查询数据是否走索引
1)不走索引
mysql> explain select * from phone where number=120;
2)走索引
mysql> explain select * from phone where number='120';
#因为120存到数据库中的字段是字符类型,那么查询时字符类型必须加引号

6)使用 like + % 的模糊匹配,当条件以%开头时

#1. % 在最前面时不走索引
mysql> explain select * from city where countrycode like '%H';
mysql> explain select * from city where countrycode like '%H%';

#2. % 在后面时走索引
mysql> explain select * from city where countrycode like 'H%';

#3. % 在中间时也走索引
mysql> select * from city where countrycode like 'C%N';

7)联合索引,插叙条件不包含建立联合索引排第一的字段时

#0.查看联合索引
mysql> show index from user;
+-------+------------+-----------+--------------+-------------+
| Table | Non_unique | Key_name  | Seq_in_index | Column_name |
+-------+------------+-----------+--------------+-------------+
| user  |          1 | index_all |            1 | sex         |
| user  |          1 | index_all |            2 | age         |
| user  |          1 | index_all |            3 | money       |
| user  |          1 | index_all |            4 | look        |
+-------+------------+-----------+--------------+-------------+

#1.只要包含排第一的字段条件,就走索引
mysql> select * from user where sex='fmale' and age='30';
mysql> explain select * from user where age='30' and money='100000000' and look='beautiful' and sex='fmale';

#2.不包含建立联合索引排第一的字段时,不走索引
mysql> explain select * from user where age='30' and money='100000000' and look='beautiful';

8) <> ,not in 不走索引

mysql> explain select * from phone where number not in (110);

mysql> explain select * from phone where number <> '110';

三、MySQL存储引擎

1.连接层
2.sql层
3.存储引擎层
	1)接收sql层传来的sql语句
	2)与磁盘交互获取数据
	
#存储引擎就是mysql的文件系统

1.MySQL提供的存储引擎

1)MySQL 提供以下存储引擎:

1.InnoDB
	数据经常添加、删除、修改、查询,使用该引擎
2.MyISAM
	只对数据进行查询和添加
3.MEMORY
	支持hash索引
4.ARCHIVE
5.FEDERATED
6.EXAMPLE
7.BLACKHOLE
8.MERGE
9.NDBCLUSTER
10.CSV

2)第三方存储引擎:

1.MySQL当中插件式的存储引擎类型
2.MySQL的两个分支
	1)perconaDB
	2)mariaDB

3)查看存储引擎

#查看当前MySQL支持的存储引擎类型
mysql> show engines

#查看innodb的表有哪些
mysql> select table_schema,table_name,engine from information_schema.tables where engine='innodb';

#查看myisam的表有哪些
mysql> select table_schema,table_name,engine from information_schema.tables where engine='myisam';

#查看某个表的信息
mysql> select * from tables where TABLE_NAME='city'\G
*************************** 1. row ***************************
  TABLE_CATALOG: def					#表的注册信息
   TABLE_SCHEMA: world					#表所在的库
     TABLE_NAME: city					#表名字
     TABLE_TYPE: BASE TABLE				#表的类型
         ENGINE: InnoDB					#存储引擎
        VERSION: 10						#默认版本
     ROW_FORMAT: Compact				#行模式
     TABLE_ROWS: 4188					#查询数据的量
 AVG_ROW_LENGTH: 97						#行数据的平均长度
    DATA_LENGTH: 409600					#数据长度
MAX_DATA_LENGTH: 0						#最大数据长度
   INDEX_LENGTH: 131072					#索引的数据长度
      DATA_FREE: 0						#空间碎片
 AUTO_INCREMENT: 4080					#自增属性的值到了多少
    CREATE_TIME: 2020-10-28 18:27:42	 #创建时间
    UPDATE_TIME: NULL					#修改时间
     CHECK_TIME: NULL					#检查时间
TABLE_COLLATION: latin1_swedish_ci		 #表的字符集
       CHECKSUM: NULL					#检查次数
 CREATE_OPTIONS: 						#建表的参数
  TABLE_COMMENT: 						#表的注释
1 row in set (0.00 sec)

2.innodb和myisam的物理区别

#myisam存储引擎的文件
-rw-rw---- 1 mysql mysql  10684 10月 19 17:09 user.frm			#表结构	
-rw-rw---- 1 mysql mysql    728 10月 23 20:02 user.MYD			#数据库的用户密码
-rw-rw---- 1 mysql mysql   2048 10月 27 08:51 user.MYI			#数据库的用户

#innodb存储引擎的文件
-rw-rw---- 1 mysql mysql    8710 10月 28 19:53 city.frm			#表结构
-rw-rw---- 1 mysql mysql 2097152 10月 28 19:54 city.ibd			#表数据

#查看文件
strings user.MYI

3.innodb的核心特性

MVCC			#多版本并发控制
事务			   #事务的特性
备份			   #mysqldump   xtrabackup
故障自动恢复		#CSR

上一篇:explain详解


下一篇:详解GaussDB(DWS) explain分布式执行计划