索引(index)是帮助MySQL进行高效数据查找的一种数据结构,在数据库中,除了数据本身之外,还维护着满足特定查找算法的数据结构,这些数据结构通过某种方式指向数据,从而可以通过这些数据结构实现高效的查找,这种数据结构就是索引。
select
) 的效率,但是降低了增 (insert
)、删(delete
)、改(update
)的效率MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构
InnoDB引擎则是采用的B+Tree索引
索引结构 | 描述 |
---|---|
B+Tree索引 | 常见的索引类型,大部分存储引擎都支持B+Tree索引 |
Hash索引 | 底层的数据结构是使用哈希表实现,只有在精确匹配到索引列的查询时才有效,不支持范围查询(如:>、<、between 等) |
R-Tree空间索引 | 空间索引时MyISAM存储引擎中的一种索引类型,主要用于地理空间数据类型,使用较少 |
Full-text全文索引 | 是通过简历倒排索引,快速匹配或查询文档的方式,类似于Elasticsearch |
这里介绍MySQL3种常见的存储引擎,如:InnoDB、MyISAM、Memory
MyISAM是MySQL早期的存储引擎,现在已经采用InnoDB做为默认存储引擎
是MySQL种基于内存的存储引擎,将数据保存到内存中,在发生断电或者其他故障的情况下,内存中的数据将会丢失,所以,一般作为缓存或者临时表使用
分类 | 描述 | 特点 | 关键字 |
---|---|---|---|
主键索引 | 针对表中的主键创建的索引 | 默认自动创建,有且仅有一个 | PRIMARY |
唯一索引 | 避免一列中的值重复,强制要求值不相同 | 可以有多个 | UNIQUE |
常规索引 | 快速查找特定的数据 | 可以有多个 | |
全文索引 | 针对文本中的关键词查找,而不是比较索引的值 | 可以有多个 | FULLTEXT |
在向字段添加了唯一约束后,会自动创建唯一索引
其中,索引又可以分为:聚簇索引、非聚簇索引(二级索引)
聚簇索引一般指代主键索引,主键索引默认为聚簇索引,其他非主键索引,是二级索引或非聚簇索引
聚簇索引的选取规则
rowid
作为聚簇索引查看索引
-- table 表示 表的名称
show index from table
创建索引
create [UNIQUE | FULLTEXT] index 索引名称 on table(字段名称)
删除索引
-- table 表示 表的名称
drop index 索引名称 on table
使用 show status
命令查询 select、insert、update、delete等语句的执行频率
show [global | session] status like 'Com_______';
如图,select 执行了18次
在MySQL中,可通过配置来记录执行较慢的SQL,从而来对SQL进行分析
通过以下命令来查询,慢查询日志功能是否开启
show variables like '%slow_query_log%';
慢查询日志记录了所有的SQL执行时间超过了指定参数(long_query_time 单位是秒,默认为10秒)的所有SQL语句的日志
在配置文件 /etc/my.cnf
中进行配置
# 开启慢查询日志开关
slow_query_log=1
# 设置慢日志的时间为2秒,如果SQL执行的时间超过了2秒,就会被当做慢SQL,就会进行慢查询日志的记录
long_query_time=2
show profiles 能够帮助我们在做SQL优化时,告诉我们在SQL执行的过程中,时间具体耗费到哪里去了
查看自己的MySQL是否支持profile,使用以下命令:
select @@have_profiling
查看此功能是否已开启,使用以下命令:
-- 查看是否开启,0:关闭;1:开启
select @@profiling;
如果没有开启,使用以下命令开启:
-- 开启
set profiling = 1;
在执行了一系列的SQL之后,使用 show profiles
查看耗时情况
查看指定 Query_ID 的各阶段耗时情况
# 查看指定的query_id的SQL语句各个阶段的耗时情况
show profile for query query_id;
如:show profile for query 32
,查询query_id是32的各阶段耗时
查看SQL语句的执行计划,只需要在SQL的最前方添加 explain
关键字运行即可
-- 如下
explain select * from table
执行计划中各字段表示的含义:
最左前缀法则是指:查询从最左列开始,并且中间不跳过索引列,如果跳过了某一列,后面的索引字段将会失效。如果建立了联合索引(多列索引),要遵循最左前缀法则
SQL提示是优化数据库的一个重要的手段,就是在SQL语句中,加入一些人为的操作,来达到优化的目的
例如:
select * from table use index(idx_table_id) where id = 1;
select * from table ignore index(idx_table_id) where id = 1;
select * from table force index(idx_table_id) where id = 1;
覆盖索引:查询使用了索引,并在查询返回的字段列上,在索引字段中全部能找到
注意: 如果查询返回的字段,没有在索引字段中找到,则需要回表查询,回表查询的效率会比直接通过索引查询的效率低
所以,在查询中,减少使用 select *
,因为 select *
非常容易造成回表查询
单列索引:一个索引只包含一列
联合索引:一个索引包含多个列
在业务场景中,如果根据多个查询条件进行查询,考虑建立联合索引,而非单列索引
在多条件联合查询时(如果多个条件都各自建立了单列索引),MySQL优化器会评估哪个索引字段的效率更高,从而选择该索引完成查询,也就是只用到其中一个索引,进而导致回表查询
not null
非空约束。当MySQL的优化器直到每列是否包含null值时,可以更好地确定哪个索引对查询更有效