文章目录
慢查询
慢查询:顾名思义,就是查询慢的日志,是指mysql记录所有执行超过long_query_time参数设定的时间阈值的SQL语句的日志。该日志能为SQL语句的优化带来很好的帮助。默认情况下,慢查询日志是关闭的,要使用慢查询日志功能,首先要开启慢查询日志功能。
show status like ‘com_insert’;—显示执行了多少次插入操作
show status like ‘com_update’;—显示执行了多少次更新
show status like ‘com_delete’;—显示执行了多少次删除
show status like ‘com_select’;—显示执行多少次查询
show status like ‘uptime’;—显示mysql数据库启动多长时间
慢查询配置
常用配置参数:
slow_query_log 启动停止技术慢查询日志
slow_query_log_file 指定慢查询日志得存储路径及文件(默认和数据文件放一起)
long_query_time 指定记录慢查询日志SQL执行时间得伐值(单位:秒,默认10秒)
log_queries_not_using_indexes 是否记录未使用索引的SQL
log_output 日志存放的地方【TABLE】【FILE】【FILE,TABLE】
show VARIABLES like ‘%slow_query_log%’
show VARIABLES like ‘%slow_query_log_file%’
show VARIABLES like ‘%long_query_time%’
show VARIABLES like ‘%log_queries_not_using_indexes%’
set global long_query_time=0;
set GLOBAL slow_query_log = 1;
记录符合条件得SQL
查询语句
数据修改语句
已经回滚得SQL
慢查询解读
慢查询工具
show status like ‘com_insert’;—显示执行了多少次插入操作
show status like ‘com_update’;—显示执行了多少次更新
show status like ‘com_delete’;—显示执行了多少次删除
show status like ‘com_select’;—显示执行多少次查询
show status like ‘uptime’;—显示mysql数据库启动多长时间
mysqldumpslow
常用的慢查询日志分析工具(mysqldumpslow)汇总除查询条件外其他完全相同的SQL,并将分析结果按照参数中所指定的顺序输出。
-s 按照那种方式排序
c:访问计数
l:锁定时间
r:返回记录
al:平均锁定时间
ar:平均访问记录数
at:平均查询时间
-t 是top n的意思,返回多少条数据。
-g 可以跟上正则匹配模式,大小写不敏感。
demo:
得到返回记录最多的20个sql
mysqldumpslow -s r -t 20 sqlslow.log
得到平均访问次数最多的20条sql
mysqldumpslow -s ar -t 20 sqlslow.log
得到平均访问次数最多,并且里面含有ttt字符的20条sql
mysqldumpslow -s ar -t 20 -g “ttt” sqldlow.log
pt_query_digest
pt-query-digest 是用于分析mysql慢查询的一个工具,与mysqldumpshow工具相比,py-query_digest 工具的分析结果更具体,更完善。
有时因为某些原因如权限不足等,无法在服务器上记录查询。这样的限制我们也常常碰到,所以开发了两种替代的技术,都集成到了Percona Toolkit 中的 pt-query-digest 中。百度安装然后参考教程即可实现基本的使用,比mysql自带的日志分析指令更好更全面。重点看里面执行计划。
索引
MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。
拿汉语字典的目录页(索引)打比方,我们可以按拼音、笔画、偏旁部首等排序的目录(索引)快速查找到需要的字。
mysql中提到,一个表最多16个索引,最大索引长度256字节.
索引的数据结构:
- HASH 索引
这个索引类似就是将我们的Key通过一个hash算法将数据映射到一个地址中去,跟Java中到HashMap的Key寻址类似,这个类型的索引只适合等值查找,对于范围性查找无能为力。 - BTREE
首先要了解TREE 然后延伸到BTREE,最后目前mysql的索引底层大部分都是B+Tree,这个类型的索引数据都存在叶子节点,比较适合范围查找。
索引分类:
普通索引:即一个索引只包含单个列,一个表可以有多个单列索引
唯一索引:索引列的值必须唯一,但允许有空值
复合索引:即一个索引包含多个列(索引负责最左原则)
聚簇索引:并不是一种单独的索引类型,而是一种数据存储方式。将数据存储与索引放到了一块,找到索引也就找到了数据,其实就是在同一个InnoDB的聚簇索引结构中保存了B-Tree索引(技术上来说是B+Tree)和数据行。
非聚簇索引:不是聚簇索引,将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行。
聚簇索引跟非聚簇索引
聚簇索引
我们在平时创建数据表的时候,在某些关系型数据库中,数据表只能有一个自增主键AUTO_INCREMENT。
如果一个表没有加索引,数据按顺序一条一条的在磁盘上按插入顺序存储着。
如果一张表一旦加了索引,比如加了自增主键,那么表中的数据在磁盘中就不是按顺序排列的,而是变成了树状结构,也就是我们常说的平衡树,换句话说就是整个表都变成了一个索引树,也就是所谓的聚簇索引。
这也就说明白了为什么一个表只能有一个自增主键以及只能有一个聚簇索引了,因为自增主键的作用根儿上就是根据一定算法把表的数据按照一定格式转换成平衡树存放在磁盘的。所谓聚簇索引,就是指:主索引文件和数据文件为同一份文件,目前我所了解的聚簇索引只是在Innodb存储引擎中存在。
在创建表的时候,INNODB类型的表存储的是一个文件,后缀为.frm。这个文件包含了数据、表结构、索引树。在数据结构实现方式中B+Tree的叶子节点中data就是数据本身,key为主键,如果是二级索引(自己创建的)的话,data便会指向对应的主索引。
当然任何事物都是有两面的,索引能让数据库查询数据的速度提升, 同时对表的写入数据速度就会下降,原因很简单的。 因为平衡树这个结构必须一直维持在一个正确的状态,增删改数据都会改变平衡树各节点中的索引数据内容,破坏树结构。
因此,在每次数据改变时,DBMS必须去重新梳理树(索引)的结构以确保它的正确,这会带来不小的性能开销,也就是为什么索引会给查询以外的操作带来副作用的原因。
MySQL中InnoDB 的主键一定是聚集索引。如果没有定义主键,聚集索引可能是第一个不允许为 null 的唯一索引,也有可能是 row id。
非聚簇索引:
其实他们俩差不多,同样都是使用平衡树作为索引的数据结构。
区别:非聚集索引这棵树中所有的节点都来自于表中二级索引字段。假如给user表的name字段加上索引 , 那么索引就是由name字段中的值构成,在数据改变时, DBMS需要一直维护索引结构的正确性。如果给表中多个字段加上索引 ,那么就会出现多个独立的索引结构,每个索引(非聚集索引)互相之间不存在关联。
每次给字段建一个新索引,字段中的数据就会被复制一份出来,用于生成索引。因此,给表添加索引,会增加表的体积,占用磁盘存储空间。
非聚集索引和聚集索引的区别在于,通过聚集索引可以查到需要查找的数据,而通过非聚集索引可以查到记录对应的主键值 ,再使用主键的值通过聚集索引查找到需要的数据,
聚集和非聚集索引不管以任何方式查询表,最终都会利用主键通过聚集索引来定位到数据,聚集索引(主键)是通往真实数据所在的唯一路径。
不过,有一种例外可以不使用聚集索引就能查询出所需要的数据这种非主流的方法称之为覆盖索引查询,也就是平时所说的复合索引或者多字段索引查询。
刚才说过了,每次给字段加一次索引,所对应的内容就会被复制出来一份。如果为一个索引指定两个字段,那么这个两个字段的内容都会被同步至索引之中。
覆盖索引可以完美的解决二级索引回表查询问题。但是前提是一定得注意查询时候索引的。最左侧匹配原则
使用聚集索引的查询效率要比非聚集索引的效率要高,但是如果需要频繁去改变聚集索引的值,写入性能并不高,因为需要移动对应数据的物理位置。
聚集索引两点关键信息:根据主键值创建了 B+ 树结构,每个叶子节点包含了整行数据。
总的来说,在MySQL中MyIsAm使用的是B+tree索引结构,叶节点的data仅仅存放的是指向数据记录的一个地址,在MyIsAm中主键索引和辅助索引没有任何区别,只是主键索引要求key是唯一的,而辅助索引的key可以重复。
在InnoDB中使用的也是B+tree索引结构,但是在实现方式来说和MyIsAm完全不通,MyIsAm的都是分开的,MyIsAm中索引文件只数据文件和索引文件以及表定义文件是存储一个指向具体数据的一个指针。但是在innodb中,Btree可以分为两种:主键索引和二级索引(也叫辅助索引)。
innodb中主键索引一定是聚集索引,表数据文件本身就是一个B+tree结构,这个树的叶节点保存了每一条记录的完整数据,这个叶节点的key就是数据的主键,innodb中二级索引保存的是索引列值以及指向主键的指针,所以我们使用覆盖索引优化其实说白了就是对MySQL的innodb索引加速的。
覆盖索引(Covering Index)
理解方式一:就是select的数据列只用从索引中就能够取得,不必读取数据行,MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件,换句话说查询列要被所建的索引覆盖。
理解方式二:索引是高效找到行的一个方法,但是一般数据库也能使用索引找到一个列的数据,因此它不必读取整个行。毕竟索引叶子节点存储了它们索引的数据;当能通过读取索引就可以得到想要的数据,那就不需要读取行了。一个索引包含了(或覆盖了)满足查询结果的数据就叫做覆盖索引。
PS:如果要使用覆盖索引,一定要注意select列表中只取出需要的列,不可select *,
总结:
MyISAM引擎中leaf node存储的内容:
主键索引 :仅仅存储行指针;二级索引:存储的也仅仅是行指针;
InnoDB引擎中leaf node存储的内容
主键索引 :聚集索引存储完整的数据(整行数据)二级索引:存储索引列值+主键信息
查看索引
SHOW INDEX FROM table_name\G
创建索引
CREATE [UNIQUE ] INDEX indexName ON mytable(columnname(length));
ALTER TABLE 表名 ADD [UNIQUE ] INDEX [indexName] ON (columnname(length))
删除索引
DROP INDEX [indexName] ON mytable;# 执行计划
重点执行计划
explain sql
explain extended sql : 扩展能够在原本explain的基础上额外的提供一些查询优化的信息,
这些信息可以通过mysql的show warnings命令得到。
执行计划:SQL执行计划,就是一条SQL语句,在数据库中实际执行的时候,一步步的分别都做了什么。就是我们用EXPLAIN分析一条SQL语句时展示出来的那些信息
意义:了解SQL执行计划的意义就在于我们可以通过执行计划更加清晰的认识到这一条语句,分为了哪几步,有没有用到索引,是否有一些可优化的地方等。
表的读取顺序
数据读取操作的操作类型
哪些索引可以使用
哪些索引被实际使用
表之间的引用
每张表有多少行被优化器查询
执行计划详解
其中最重要的字段为:id、type、key()、rows、Extra
- id 可以看到大致的执行顺序
- type可以看到每个table执行到类型
- key 可以看到 使用到索引
- rows 可以看到 每个表扫描的行数
- Extra 包含很多重要额外信息,
- key_len 可以看出联合索引计算的是索引长度和,由此延伸判断。
具体的字段含义可看blog
重点 MySQL优化
- 尽量全值匹配
当建立了索引列后,能在where条件中使用索引的尽量所用
- 最佳左前缀法则
如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。
- 不在索引列上做任何操作
不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
- 范围条件放最后
WHERE NAME = ‘July’ and age >22 and pos=‘manager’,会导致 age 后的索引失效。
- 覆盖索引尽量用
尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *
- 不等于要慎用
mysql 在使用不等于(!= 或者<>)的时候无法使用索引会导致全表扫描
- Null/Not 有影响
注意null/not null对索引的可能影响
在字段为not null的情况下,使用is null 或 is not null 会导致索引失效,解决方式:覆盖索引
- 策略8.Like查询要当心
like以通配符开头(’%abc…’) mysql索引失效会变成全表扫描的操作,解决方式:覆盖索引或 通配符%尽量靠后。
- 字符类型加引号
字符串不加单引号索引失效,解决方式:请加引号
- OR改UNION效率高
查询用union来实现,或者使用覆盖索引。注意on也是where查询一种