MySQL学习(优化)

文章目录

统计信息

  • 查看当前会话SQL执行类型的统计信息
sql 复制代码
show session status like 'Com_______';
  • 查看全局(上次服务器启动至今)SQL执行类型的统计信息
sql 复制代码
show global status like 'Com_______';
  • 查看针对InnoDB的SQL执行类型的统计信息
sql 复制代码
show status like 'Innodb_rows_%';

定位低效率执行SQL

  • 慢查询日志(上一节)和show processlist
  • show processlist;
    id:当前执行的线程ID,可以使用函数connection_id()查看
    user:执行该语句的用户
    host:执行该语句的客户端IP和端口
    db:当前执行的数据库
    command:当前执行的命令状态,如sleep、query、connect等
    time:执行该语句所消耗的时间,单位秒
    state:当前SQL的执行状态
    info:当前执行的SQL语句,可以判断问题语句

explain分析执行计划

  • 可以获取SQL语句的执行信息,包括表如何连接和连接的顺序,SQL语句是否用到索引等
sql 复制代码
explain select * from emp a where a.empno=7369;
sql 复制代码
/*
    id:select查询的序列号,是一组数字,表示的是执行select子句或操作表的顺序
    select_type:表示查询的类型,SIMPLE(简单select,不使用union或子查询)、PRIMARY(主查询,最外层的select)、
                UNION(UNION中的第二个或后面的SELECT语句)、SUBQUERY(子查询中的第一个SELECT)等
    table:表示查询涉及的表或衍生表
    type:表示表的连接类型,性能由好到差的连接类型为system、const、eq_reg、ref、range、index和all
    possible_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

sql 复制代码
-- id相同时,执行顺序由上至下
    explain select * from emp a,dept b where a.empno=7369 and a.deptno=b.deptno;
-- id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
    explain select * from dept b where b.deptno = (select a.deptno from emp a where a.empno=7839);

select_type

sql 复制代码
-- SIMPLE:简单select,不使用UNION或子查询等
explain select * from emp;  -- SIMPLE
explain select * from emp a, dept b where a.deptno=b.deptno;    -- SIMPLE
-- PRIMARY:主查询,子查询最外层查询控制
-- SUBQUERY:子查询内层第一个select语句
explain select * from dept b where b.deptno = (select a.deptno from emp a where a.empno=7839);    -- PRIMARY和SUBQUERY
-- DERIVED:派生表,from子句中的子查询
explain select * from (select * from emp limit 2) a;    -- DERIVED
-- UNION:UNION语句中第二个select开始
-- UNION RESULT:从union结果集获取结果的select
explain select * from emp a where a.empno=7369 union select * from emp b where b.empno=7839;    -- UNION和UNION RESULT

type

sql 复制代码
 explain select * from emp;  -- ALL:全表扫描
 -- NULL:不访问任何表和索引直接返回结果
 explain select now();
 -- system:查询系统表,直接从内存读取数据,不会从磁盘读取数据,5.7版本之后不显示system而是all
 explain select * from mysql.user;
 -- const:通过索引一次就找到,用于主键或唯一索引扫描
 explain select * from emp a where a.empno=7369;
 -- eq_ref:左表有主键约束,且与右表的数据一一对应,右表查询时,左表的type是eq_ref
     -- 创建符合要求的表
         create table user1(id int, name varchar(20));
         insert into user1 values(1, '张三'), (2, '李四'), (3, '王五');
         create table user2(id int, age int);
         insert into user2 values(1, 30), (2, 40), (3, 50);
     -- 无主键时执行查询
         explain select * from user1 a,user2 b where a.id=b.id;  -- all,all
     -- 给user1表添加主键时执行查询
         alter table user1 add primary key(id);
         explain select * from user1 a,user2 b where a.id=b.id;  -- eq_ref,all
 -- ref:非唯一索引扫描,返回匹配某个单独值的所有行
     -- 删除user1表的primary key
         alter table user1 drop primary key;
     -- 添加普通索引
         create index idx_id on user1(id);
     -- 执行查询
         explain select * from user1 a,user2 b where a.id=b.id;  -- ref,all
 -- range:索引范围扫描,对索引列执行范围查询
     explain select * from emp a where a.empno between 7369 and 7839;    -- range
 -- index:索引全表扫描,把索引从头到尾扫一遍
     explain select a.empno from emp a;  -- index

show profiles分析

sql 复制代码
-- 查看是否支持profile
    select @@have_profiling;
-- 开启profile
    set profiling=1;
-- 执行SQL
    show databases;
    use test1;
    show tables;
    select count(*) from emp;
-- 查看profile
    show profiles;
-- 查看profile详情
    show profile for query 44;
-- 查看cpu情况(可选all 所有,block io 块io,context switch 上下文切换,page faults 页面错误)
    show profile cpu for query 67;

trace分析优化器执行计划

sql 复制代码
-- 开启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;
-- 查看trace
select * from information_schema.optimizer_trace \G;    -- 这条语句要在cmd中运行

避免索引失效

sql 复制代码
/*
   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. 尽量使用复合索引,因为单列索引最多只会生效一个最优的
*/

SQL优化

从本地导入数据

sql 复制代码
show global variables like 'local_infile';  -- 查看是否开启允许从本地导入数据
set global local_infile=1;  -- 开启允许从本地导入数据
sql 复制代码
-- load data local infile '本地数据文件路径' into table 表名 fields terminated by ',' lines terminated by '\n';
-- fields 指定字段分割符,lines 指定行分隔符

-- 数据最好让主键有序,这样导入更快
-- 关闭唯一性校验
   set unique_checks=0;

优化insert语句

sql 复制代码
/*
    1. 不要多次使用insert into,在一条insert into 中插入多条数据,如insert into values(),()...
    2. 在手动事务中进行数据插入
    3. 数据有序插入
*/

优化order by语句

sql 复制代码
create index idx_name_sal on emp(sal, ename);
drop index idx_name_sal on emp;
explain select * from emp a order by a.sal;     -- Using filesort
explain select a.empno from emp a order by a.sal;    -- Using index
-- order by 后面多个排序字段尽量排序方式相同
explain select a.empno from emp a order by a.sal desc, a.ename;     -- Using index & Using filesort
explain select a.empno from emp a order by a.sal, a.ename;    -- Using index
-- order by 后面多个排序字段尽量与组合索引顺序一致
explain select a.empno from emp a order by a.ename, a.sal;    -- Using index & Using filesort

优化filesort

sql 复制代码
show variables like 'max_length_for_sort_data'; -- 4096
show variables like 'sort_buffer_size'; -- 262144
-- 增大这两个值,使得程序优选一次扫描算法,占用内存开销,提高排序效率

优化子查询: 将子查询优化为join

sql 复制代码
explain select * from emp a where a.deptno in (select b.deptno from dept b);
explain select * from emp a join dept b on a.deptno=b.deptno;

优化limit查询

sql 复制代码
-- 如果查询从第100万条数据向后10条数据,需要对100万加10条数据排序,但只取10条数据,代价过大
-- 1. 在索引上完成排序分页操作,最后根据主键关联回原表查询所需的其他列
-- 2. 主键自增的表,比如id 直接大于100万,再limit 10
相关推荐
OEC小胖胖1 小时前
Spring MVC系统学习(一)——初识Spring MVC框架
java·后端·学习·spring·mvc
今心上1 小时前
SQL 查询语句的顺序详解
数据库·sql
code.song1 小时前
教师工作量|基于springBoot的教师工作量管理系统设计与实现(附项目源码+论文+数据库)
数据库·spring boot·后端
Python私教1 小时前
macOS安装Redis教程, 通过brew命令, 时间是2024年9月26日, redis版本是0.7.2
数据库·redis·macos
API199701081102 小时前
深度探索与实战编码:利用Python与AWS签名机制高效接入亚马逊Product Advertising API获取商品详情
数据库·python·aws
H2Z20Str2 小时前
Linux学习笔记13---GPIO 中断实验
linux·笔记·学习
007php0072 小时前
在Kubernetes中部署PHP项目的完整指南
学习·云原生·容器·架构·golang·kubernetes·php
weightOneMillion2 小时前
鸿蒙界面开发(九):列表布局 (List)
前端·学习·华为·list·harmonyos
Pfirsich Zhang2 小时前
Redis相关知识
数据库·redis·缓存