MySQL数据库--查询截取分析

查询截取分析

分析:

1.观察,至少跑一天,看看生产的SQL的情况

2.开启慢查询日志,设置阀值

3.explain+慢sql分析

4.show profile 分析力度更强

5.运维经理或dba进行sql数据库服务器的参数调优

小表驱动大表

数据库最伤神的就是进行连接和释放

当A数据集的量大于B数据集的量时使用in

select * from a where id in (select id from b)
相当于:
for select id from b
for select * from a where a.id = b.id

当A数据集的量小于B数据集的量时使用exists

select * from a where exists (select 1 from b where a.id = b.id);
相当于
for select * from a
for select * from b where b.id=a.id

exists语法可以理解为
将主查询的数据,放到子查询中去做条件验证,根据验证结果来决定主查询的数据结果是否得以保存
Order by 优化

如果order by 的顺序也会索引的顺序相同一致且都为asc 或都为desc的话,就可以用索引而没有filsort

mysql 支持两种方式排序,user index user filesort index执行效率高

order by 满足两情况时使用index方式排序:

  • order by 语句使用索引最左前列
  • 使用where子句与order by子句条件列组合满足索引最左前列

仅可能在索引列上完成排序操作,遵照索引键的最佳左前缀

filesort 有两种算法:

​ 双路排序:两次扫描磁盘

​ 单路排序:一次扫描磁盘,需要更多的空间,它吧每一行都保存在内存中

优化策略:

​ 1.增加sort_buffer_size参数

​ 2.增大manx_length_for_sort_data参数的设置(提高使用改进算法的概率)

​ 3.只要加order by 最好不要使用select *,因为select *涉及字段太多,容易把sort_buffer缓冲区用满

若容量超出,则会创建临时文件进行合并排序,导致多次io,若query字段大小综合小于manx_length_for_sort_data时而排序字段不时text/blob类型时,会使用改进的算法,单路排序

使用方法:

key_a_b_c

1.order by 能使用索引最左前缀

​ order by a

​ order by a,b

​ order by a,b,c

​ order by a desc,b desc,c desc

2.如果where使用索引的最左前缀定义为常量,则oreder by能使用索引

​ where a=const order by b,c

​ where a=const and b=const order by c

​ where a = const and b > const order by b,c

不能使用方法:

​ order by a desc ,b ,c desc排序不一致,

​ where g = cosnt order by b,c 丢失a索引,

​ where a=cosnt order bu c, 丢失b索引

​ where a = const order by a,d d不是索引的一部分

​ where a in (…) order by b,c 对于排序来说,多相等条件也是范围查询

group by优化

​ 和sort by一样但是多了一点:

​ where 高于having,能写where限定条件就不要去having限定了

慢查询日志分析

默认情况下,没有开启慢查询,若不是调优需要,不建议启动。

查看是否开启 ;show variable like “%slow _query_log%”;

​ set slow _query_log = 1

查看默认阀值: show variable like “long_query_time%” 默认十秒

​ 修改为3秒,需重新连接或重开会话才能看到修改值

select sleep (4);休眠四秒

查看当前系统多少条慢查询:shwo variables like “%Slow_queries%”

配置:

​ slow_query_log=1

​ slow_query_log_file = /var/lib/mysql/aiguigi.log

​ long_query_time=3

​ log_output=FILE

批量插入数据脚本
#创建数据库
create database bigData;
use bigData;

# 建表opt
create table opt(
id int unsigned primary key auto_increment,
deptno mediumint unsigned not null default 0,
dname varchar(20) not null default "",
loc varchar(13) not null default "");

# 建表emp
create table emp(
id int unsigned primary key auto_increment,
empno mediumint unsigned not null default 0,
ename varchar(20) not null default "",
job varchar(9) not null default "",
mgr mediumint unsigned not null default 0,
hiredate DATE NOT NULL,
sal decimal(7.2) not null,
comm decimal(7.2) not null,
deptno mediumint unsigned not null default 0);

#设置二进制日志
set global log_bin_trust_function_creators = 1;

#创建函数,保证每条数据都不同
#1.随机产生字符串
delimiter $$
create function rand_string(n int)returns varchar(255)
begin
declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ';
declare return_str varchar(255) default '';
declare i int default 0;
while i < N DO
set return_str = concat(return_str,SUBSTRING(chars_str,floor(1+rand()*52),1));
set i = i +1;
end while;
return return_str;
end $$

#2.随机产生部门编号
create function rand_num() returns int(5)
begin
declare i int default 0;
set i = floor(100+rand()*10);
return i; 
end $$

#创建存储过程
#1.插入emp
create procedure insert_emp(in start int(10),in max_num int(10))
begin 
declare i int default 0;
set autocommit = 0;
repeat
set i = i +1;
insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values((start+i),rand_string(6),'salesman',0001,CURRENT_DATE(),2000,400,rand_num());
until i = max_num
end repeat;
commit;
end $$
#2.插入opt
create procedure insert_dept(in start int(10),in max_num int(10))
begin 
declare i int default 0;
set autocommit = 0;
repeat
set i = i +1;
insert into dept(deptno,dname,loc) values((start+i),rand_string(10),rand_string(8));
until i = max_num
end repeat;
commit;
end $$

#调用存储过程
delimiter ;
# dept插入数据
call insert_dept(100,10);
# emp插入数据
call insert_emp(100001,500000);

show profile进行分析

查看状态show variables like “profiling”

开启 set profiling =1;

编写sql语句:

​ select * from emp group by id%10 limit 150000;

查看所有执行过的sql:show profiles;

诊断:show profile cpu,block io for query 查询id;

显示整个查询的完整周期

选项出现证明有问题:

converting HEAP to Myisam 查询结果太大,内存不够用往磁盘上搬了

creating tmp table 创建临时表(拷贝数据到临时表,用完再删除)

copying to tmp table on disk 吧内存中的临时表复制到磁盘

locked

四个中有任何一个都需要优化

全局查询日志

只允许测试环境用

启动:

​ set global genral_log=1;

​ set global log_outout=‘TABLE’; 以表的形式输出

​ 记录到mysql 的general_log表中

​ select * from mysql.general_log;

猜你喜欢

转载自blog.csdn.net/MINGZHEFENG/article/details/106904450