show processlist; id:当前执行的线程ID,可以使用函数connection_id()查看 user:执行该语句的用户 host:执行该语句的客户端IP和端口 db:当前执行的数据库 command:当前执行的命令状态,如sleep、query、connect等 time:执行该语句所消耗的时间,单位秒 state:当前SQL的执行状态 info:当前执行的SQL语句,可以判断问题语句
explain分析执行计划
可以获取SQL语句的执行信息,包括表如何连接和连接的顺序,SQL语句是否用到索引等
explainselect*from emp a where a.empno=7369;
/*id:select查询的序列号,是一组数字,表示的是执行select子句或操作表的顺序select_type:表示查询的类型,SIMPLE(简单select,不使用union或子查询)、PRIMARY(主查询,最外层的select)、UNION(UNION中的第二个或后面的SELECT语句)、SUBQUERY(子查询中的第一个SELECT)等table:表示查询涉及的表或衍生表type:表示表的连接类型,性能由好到差的连接类型为system、const、eq_reg、ref、range、index和allpossible_keys:表示查询可能使用到的索引key:表示实际使用的索引key_len:索引的长度ref:表之间的引用,即哪些列或常量被用于和前表进行连接rows:扫描的行数,估算的值filtered:按表条件过滤的行数的百分比extra:额外的信息Using filesort:说明MySQL会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取Using temporary:使用了临时表保存中间结果,MySQL在对查询结果排序时使用临时表,比如分组Using index:SQL所需要返回的所有列数据都在一棵索引树上,避免访问表的数据行,比如按照索引列分组Using where:在查找使用索引的情况下,需要回表去查询所需数据Using index condition:查找使用索引,但是需要回表查询数据Using index,Using where :在查找使用索引的情况下,不需要回表查询数据
*/
id
-- id相同时,执行顺序由上至下explainselect*from emp a,dept b where a.empno=7369and a.deptno=b.deptno;-- id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行explainselect*from dept b where b.deptno =(select a.deptno from emp a where a.empno=7839);
select_type
-- SIMPLE:简单select,不使用UNION或子查询等explainselect*from emp;-- SIMPLEexplainselect*from emp a, dept b where a.deptno=b.deptno;-- SIMPLE-- PRIMARY:主查询,子查询最外层查询控制-- SUBQUERY:子查询内层第一个select语句explainselect*from dept b where b.deptno =(select a.deptno from emp a where a.empno=7839);-- PRIMARY和SUBQUERY-- DERIVED:派生表,from子句中的子查询explainselect*from(select*from emp limit2) a;-- DERIVED-- UNION:UNION语句中第二个select开始-- UNION RESULT:从union结果集获取结果的selectexplainselect*from emp a where a.empno=7369unionselect*from emp b where b.empno=7839;-- UNION和UNION RESULT
type
explainselect*from emp;-- ALL:全表扫描-- NULL:不访问任何表和索引直接返回结果explainselectnow();-- system:查询系统表,直接从内存读取数据,不会从磁盘读取数据,5.7版本之后不显示system而是allexplainselect*from mysql.user;-- const:通过索引一次就找到,用于主键或唯一索引扫描explainselect*from emp a where a.empno=7369;-- eq_ref:左表有主键约束,且与右表的数据一一对应,右表查询时,左表的type是eq_ref-- 创建符合要求的表createtable user1(id int, name varchar(20));insertinto user1 values(1,'张三'),(2,'李四'),(3,'王五');createtable user2(id int, age int);insertinto user2 values(1,30),(2,40),(3,50);-- 无主键时执行查询explainselect*from user1 a,user2 b where a.id=b.id;-- all,all-- 给user1表添加主键时执行查询altertable user1 addprimarykey(id);explainselect*from user1 a,user2 b where a.id=b.id;-- eq_ref,all-- ref:非唯一索引扫描,返回匹配某个单独值的所有行-- 删除user1表的primary keyaltertable user1 dropprimarykey;-- 添加普通索引createindex idx_id on user1(id);-- 执行查询explainselect*from user1 a,user2 b where a.id=b.id;-- ref,all-- range:索引范围扫描,对索引列执行范围查询explainselect*from emp a where a.empno between7369and7839;-- range-- index:索引全表扫描,把索引从头到尾扫一遍explainselect a.empno from emp a;-- index
show profiles分析
-- 查看是否支持profileselect @@have_profiling;-- 开启profileset profiling=1;-- 执行SQLshowdatabases;use test1;showtables;selectcount(*)from emp;-- 查看profileshow profiles;-- 查看profile详情show profile for query 44;-- 查看cpu情况(可选all 所有,block io 块io,context switch 上下文切换,page faults 页面错误)show profile cpu for query 67;
trace分析优化器执行计划
-- 开启trace,设置格式为json,并设置trace最大可使用的内存大小set optimizer_trace="enabled=on", end_markers_in_json=on, optimizer_trace_max_mem_size=1000000;select*from emp a, dept b where a.deptno=b.deptno;-- 查看traceselect*from information_schema.optimizer_trace \G;-- 这条语句要在cmd中运行
避免索引失效
/*1. 组合查询最左原则2. 范围查询右边的索引失效3. 不要在索引列上使用函数或运算4. 字符串不加单引号索引失效5. 尽量避免select *,用具体字段代替6. or分隔的条件,or条件列索引失效7. %开头的like索引失效(弥补不足,不要select *,使用索引列代替)8. 如果索引比全表扫描更慢,索引失效9. is null和is not null当数据null少时is not null失效,当数据null多时is null失效10. 当主键索引时,in和not in都有效,当为普通索引时,in有效,not in失效11. 尽量使用复合索引,因为单列索引最多只会生效一个最优的
*/
-- load data local infile '本地数据文件路径' into table 表名 fields terminated by ',' lines terminated by '\n';-- fields 指定字段分割符,lines 指定行分隔符-- 数据最好让主键有序,这样导入更快-- 关闭唯一性校验set unique_checks=0;
优化insert语句
/*1. 不要多次使用insert into,在一条insert into 中插入多条数据,如insert into values(),()...2. 在手动事务中进行数据插入3. 数据有序插入
*/
优化order by语句
createindex idx_name_sal on emp(sal, ename);dropindex idx_name_sal on emp;explainselect*from emp a orderby a.sal;-- Using filesortexplainselect a.empno from emp a orderby a.sal;-- Using index-- order by 后面多个排序字段尽量排序方式相同explainselect a.empno from emp a orderby a.sal desc, a.ename;-- Using index & Using filesortexplainselect a.empno from emp a orderby a.sal, a.ename;-- Using index-- order by 后面多个排序字段尽量与组合索引顺序一致explainselect a.empno from emp a orderby a.ename, a.sal;-- Using index & Using filesort
优化filesort
show variables like'max_length_for_sort_data';-- 4096show variables like'sort_buffer_size';-- 262144-- 增大这两个值,使得程序优选一次扫描算法,占用内存开销,提高排序效率
优化子查询: 将子查询优化为join
explainselect*from emp a where a.deptno in(select b.deptno from dept b);explainselect*from emp a join dept b on a.deptno=b.deptno;