优化sql语句步骤:
1.发现问题
2.分析执行计划
3.优化索引
4.改写sql
(再达不到优化效果的话 进行数据库分库分表)
1.发现问题途径
1.用户上报性能问题
2.慢查询日志发现问题SQL
3.数据库实时监控长时间运行的SQL
2.设置MYSQL
set global slow_query_log = on/off (慢查询开关)
set global slow_query_log_file = /地址 (慢查询地址)
set global long_query_time = xx.xx秒 (超过XX秒会被记录)
set global log_queries_not_using_indexes = on/off (记录没有使用索引的慢查询)
3.分析慢查询日志
1.mysqldumpslow (mysql自带)
2.pt-query-digest
4.安装percona-toolkit-3.0.13
下载软件包:
wget https://www.percona.com/downloads/percona-toolkit/3.0.13/binary/redhat/7/x86_64/percona-toolkit-3.0.13-1.el7.x86_64.rpm 安装依赖包: yum install -y perl-DBD-MySQL.x86_64 perl-DBI.x86 perl-Time-HiRes.x86_64 perl-IO-Socket-SSL.noarch perl-TermReadKey.x86_64 perl-Digest-MD5 安装 rpm -ivh percona-tookot-3.0.13-1.el7.x86_64.rpm 输入pt 按 tab 获取所有软件
5.慢查询日志设置 与 查询日志
查看各参数的值
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 slow_query_log = on/off (慢查询开关) set global slow_query_log_file = /地址 (慢查询地址) set global long_query_time = xx.xx秒 (超过XX秒会被记录) set global log_queries_not_using_indexes = on/off (记录没有使用索引的慢查询) 查看日志 mysql> show variables like 'slow_query_log_file'; +---------------------+-----------------------------------+ | Variable_name | Value | +---------------------+-----------------------------------+ | slow_query_log_file | /var/lib/mysql/localhost-slow.log | +---------------------+-----------------------------------+ 1 row in set (0.01 sec) more /var/lib/mysql/localhost-slow.log # Time: 2019-06-07T08:48:26.661099Z # User@Host: root[root] @ localhost [] Id: 12 # Query_time: 0.001453 Lock_time: 0.000257 Rows_sent: 1 Rows_examined: 0 SET timestamp=1559897306; EXPLAIN select * from student; 其中 query_time(执行sql时间) lock_time(锁的时间) rows_sent(查询返回的行数) Rows_examined(扫描的行数)
6.实时监控长时间运行的SQL
select id,user,host,db,command,time,state,info from information_schema.PROCESSLIST WHERE TIME>=60 (sql执行时间大于60秒的SQL)
7.分析执行计划
为什么分析执行计划
1.SQL如何访问表中的数据
2.了解SQL如何使用表中的索引
3.了解SQL所使用的查询类型
获取执行计划 EXPLAIN select * from XXX
8.分析执行计划
id列
为数字或者为no
id列相同时由上到下执行
id不同时,由大到小
select_type列
子查询
simple 不包含子查询或者 UNION查询
primary 查询中如果包含任何子查询,最外层的标记为primary
subquery 子查询
dependent subquery (依赖关系 子查询)
UNION查询
union union查询的第二条或者之后的
dependent union (依赖关系 子查询 ,union 语句作为子查询,union查询的第二条或者之后的)
union result 产生的结果集
derived 出现在from子句中的子查询
table列
输出表的名称
<union M,N> 由ID为M,N union后产生的结果集
<derived N>/<subquery N> 由ID为N的查询产生的结果集
partitions列
查分区表
type 列 (性能从高到低)
system (性能高)
const连接类型,当查询表只有一行时
const
表中值有且只有一行匹配,或者利用where 查询某个常量的值,主键或唯一索引查询是效率最高的方式
eq_ref(常出现在join查询 )
唯一索引或主键索引查找,对每个索引键,表中只有一条记录与之匹配
ref
非唯一索引查找,返回匹配某个单独值的所有行
ref_or_null
类似于ref 增加了null值的查询
index_merge
索引合并
range
索引范围素描(between , > , <)
index
full index scan 全索引扫描
all (性能最低)
全表扫描
key列
(possible_keys)可能会被使用到的索引
(keys)会被使用到的索引
(key_len) 实际使用索引的最大长度 (字节)
ref列
列出哪些列被用于索引查找
rows列
预估扫描行数
filtered列
返回行数与扫描行数的百分比(越高 就 性能越高)
extra列
distinct 找到第一个值后立刻停止找同值的动作
not exists 使用not exists优化 使用不存在于某个条件的查询
using filesort 常见使用order by 或者 group by 查找
using index 使用了覆盖索引(直接通过索引获取数据,不访问表)
using temporary使用了临时表
using where 使用了where
select tables optimized away 操作已经优化到不能再优化了(MySQL根本没有遍历表或索引就返回数据了)。