热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

MySQL查询截取的深入分析

这篇文章主要给大家介绍了关于MySQL查询截取的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、查询优化

1,mysql的调优大纲

  • 慢查询的开启并捕获
  • explain+慢SQL分析
  • show profile查询SQL在Mysql服务器里面的执行细节和生命周期情况
  • SQL数据库服务器的参数调优

2,小表驱动大表

  mysql的join实现原理是,以驱动表的数据为基础,“嵌套循环”去被驱动表匹配记录。驱动表的索引会失效,而被驱动表的索引有效。

#假设 a表10000数据,b表20数据
select * from a join b on a.bid =b.id
a表驱动b表为:
for 20条数据
 匹配10000数据(根据on a.bid=b.id的连接条件,进行B+树查找)
查找次数为:20+ log10000
b表驱动a表为
for 10000条数据
 匹配20条数据(根据on a.bid=b.id的连接条件,进行B+树查找)查找次数为:10000+ log20

3,in和exists

  exists的使用

  • EXISTS 语法:EXISTS(subquery) 只返回TRUE或FALSE,因此子查询中的SELECT *也可以是SELECT 1或其他,官方说法是实际执行时会忽略SELECT清单,因此没有区别
    • SELECT ... FROM table WHERE EXISTS(subquery)
    • 该语法可以理解为:将查询的数据,放到子查询中做条件验证,根据验证结果(TRUE或FALSE)来决定主查询的数据结果是否得以保留。
  • EXISTS子查询的实际执行过程可能经过了优化而不是我们理解上的逐条对比,如果担忧效率问题,可进行实际检验以确定是否有效率问题。
  • EXISTS子查询往往也可以用条件表达式、其他子查询或者JOIN来替代,何种最优需要具体问题具体分析
#采用in则是,内表B驱动外表A
select * from A where id in (select id from B)
#采用exists则是,外表A驱动内表B
select * from A where exists(select 1 from B where B.id = A.id)

  结论:

永远记住小表驱动大表
当 B 表数据集小于 A 表数据集时,使用 in
当 A 表数据集小于 B 表数据集时,使用 exist

4,orderby创建表

create table tblA(
 #id int primary key not null auto_increment,
 age int,
 birth timestamp not null
);

insert into tblA(age, birth) values(22, now());
insert into tblA(age, birth) values(23, now());
insert into tblA(age, birth) values(24, now());
#创建复合索引
create index idx_A_ageBirth on tblA(age, birth);

orderby命中索引的情况

orderby未命中索引的情况

  • MySQL支持两种排序方式:Using index和Using filesort。filesort效率较低,而要使用index方式排序需满足两种使用条件尽可能在索引列上完成排序操作,遵照索引的最佳左前缀
    • order by语句自身使用索引的最左前列
    • 使用where子句与order by子句条件列组合满足最左前列
  • 如果order by不在索引列上,会使用filesort算法:双路排序和单路排序
    • MySQL4.1之前是使用双路排序,字面意思是两次扫描磁盘,最终得到数据。读取行指针和order by列,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读取对应的数据传输
    • 从磁盘读取查询需要的所有列,按照order by列在buffer对它们进行排序,然后扫描排序后的列表进行输出,它的效率更快一些,避免了第二次读取数据,并且把随机IO变成顺序IO,但是它会使用更多的空间,因为它把每一行都保存在内存中了。
select * from user where name = "zs" order by age
#双路排序
1)从 name 找到第一个满足 name = 'zs' 的主键id
2)根据主键 id 取出整行,把排序字段 age 和主键 id 这两个字段放到 sort buffer(排序缓存) 中
3)从name 取下一个满足 name = 'zs' 记录的主键 id
4)重复 2、3 直到不满足 name = 'zs'
5)对 sort_buffer 中的字段 age 和主键 id 按照字段 age进行排序
6)遍历排序好的 id 和字段 age ,按照 id 的值回到原表中取出 所有字段的值返回给客户端

#单路排序
1)从name找到第一个满足 name ='zs' 条件的主键 id
2)根据主键 id 取出整行,取出所有字段的值,存入 sort_buffer(排序缓存)中
3)从索引name找到下一个满足 name = 'zs' 条件的主键 id
4)重复步骤 2、3 直到不满足 name = 'zs'
5)对 sort_buffer 中的数据按照字段 age 进行排序,返回结果给客户端

单路排序的问题及优化

问题:
 由于单路是改进的算法,总体而言好过双路
 在sort_buffer中,方法B比方法A要多占用很多空间,因为方法B是把所有字段都取出,所以有可能取出的数据的总大小超出了sort_buffer的容量,导致每次只能取sort_buffer容量大小的数据,进行排序(创建tmp文件,多路合并),排完再取取sort_buffer容量大小,再排…… 从而会导致多次I/O。
优化策略:
 增大sort_buffer_size参数的设置
 增大max_length_for_sort_data参数的设置
注意事项:
  Order by时select *是一个大忌,只Query需要的字段。因为字段越多在内存中存储的数据也就也多,这样就导致每次I/O能加载的数据列越少。

5,groupby优化

1)group by实质是先排序后进行分组,遵照索引的最佳左前缀
2)当无法使用索引列,增大max_length_for_sort_data参数的设置+增大sort_buffer_size参数的设置
3)where高于having,能写在where限定的条件就不要去having限定了
4)其余的规则均和 order by 一致

二、慢查询日志

1,慢查询日志是什么?

  1. MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。
  2. long_query_time的默认值为10,意思是运行10秒以上的SQL语句会被记录下来
  3. 由他来查看哪些SQL超出了我们的最大忍耐时间值,比如一条sql执行超过5秒钟,我们就算慢SQL,希望能收集超过5秒的sql,结合之前explain进行全面分析。

2,慢查询日志的开启

  默认情况下,MySQL的慢查询日志是没有开启的。如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询日志会影响到性能,慢查询日志支持将日志记录写入文件。

a)开启慢查询日志

#查看是否开启慢日志
show variables like 'slow_query_log%';
#开启慢查询日志,想要永久有效在my.cnf中设置
set global slow_query_log = 1 ;

b)设置慢查询日志的阈值

#查看慢查询日志的阈值时间 默认为10s
show variables like 'long_query_time%';
#设置为3s 重启失效,想要永久有效在my.cnf中设置
set global long_query_time = 3
#再次查看,需要切换窗口查看
show variables like 'long_query_time%';

c)持久化慢查询日志和时间阈值

[mysqld]
#持久化慢查询日志
slow_query_log=1;
slow_query_log_file=/var/lib/mysql/hadoop102-slow.log
long_query_time=3;
log_output=FILE

d)慢查询案例

#查询等待4s
select sleep(4); 
#在linux系统中,查看慢查询日志
cat /var/lib/mysql/hadoop102-slow.log

e)查看当前系统中存在的慢查询日志条数

show global status like '%Slow_queries%';

3,日志分析命令mysqldumpslow

a)参数解释

-s:是表示按何种方式排序
c:访问次数
l:锁定时间
r:返回记录
t:查询时间
al:平均锁定时间
ar:平均返回记录数
at:平均查询时间
-t:即为返回前面多少条的数据
-g:后边搭配一个正则匹配模式,大小写不敏感的

b)常用方法

#得到返回记录集最多的10个SQL
mysqldumpslow -s r -t 10 /var/lib/mysql/hadoop102-slow.log
#得到访问次数最多的10个SQL
mysqldumpslow -s c -t 10 /var/lib/mysql/hadoop102-slow.log
#得到按照时间排序的前10条里面含有左连接的查询语句
mysqldumpslow -s t -t 10 -g "left join" /var/lib/mysql/hadoop102-slow.log
#这些命令时结合 | 和more使用
mysqldumpslow -s r -t 10 /var/lib/mysql/hadoop102-slow.log | more

三、批量写数据脚本

1,建表

CREATE TABLE dept
(
 deptno int unsigned primary key auto_increment,
 dname varchar(20) not null default '',
 loc varchar(8) not null default ''
)ENGINE=INNODB DEFAULT CHARSET=utf8;

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
)ENGINE=INNODB DEFAULT CHARSET=utf8;

2,设置是否可以信任存储函数创建者

#查看binlog状态
show variables like 'log_bin%';
#添加可以信任存储函数创建者
set global log_bin_trust_function_creators = 1;

3,创建函数

随机产生字符串的函数

# 定义两个 $$ 表示结束 (替换原先的;)
delimiter $$ 
create function rand_string(n int) returns varchar(255)
begin
 declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
 declare return_str varchar(255) default '';
 declare i int default 0;
 while i 

随机产生部门编号的函数

delimiter $$
create function rand_num() returns int(5)
begin
 declare i int default 0;
 set i=floor(100+rand()*10);
 return i;
end $$

4,创建存储过程

创建往emp表中插入数据的存储过程

delimiter $$
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,curdate(),2000,400,rand_num());
 until i=max_num
 end repeat;
 commit;
end $$

创建往dept表中插入数据的存储过程

delimiter $$
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 $$

5,调用存储过程生成数据

#向 部门表插入10条数据
DELIMITER ;
CALL insert_dept(100, 10);
#向 员工表插入50w条数据
CALL insert_emp(100001, 500000);

四、show profiles

1,介绍

  • show profile是mysql提供可以用来分析当前会话中语句执行的资源消耗情况。可以用于SQL的调优测量。
  • 默认情况下,参数处于关闭状态,并保存最近15次的运行结果

2,开启

#查看 Show Profile 是否开启
show variables like ‘profiling%';
#开启 Show Profile
set profiling=on;

3,使用show profiles

创建测试数据

select * from emp group by id%10 limit 150000;
select * from emp group by id%10 limit 150000;
select * from emp group by id%10 order by 5;
select * from emp
select * from dept
select * from emp left join dept on emp.deptno = dept.deptno

执行show profiles

执行 show profile cpu, block io for query Query_ID;

检索参数

ALL:显示所有的开销信息
BLOCK IO:显示块IO相关开销
CONTEXT SWITCHES:上下文切换相关开销
CPU:显示CPU相关开销信息
IPC:显示发送和接收相关开销信息
MEMORY:显示内存相关开销信息
PAGE FAULTS:显示页面错误相关开销信息
SOURCE:显示和Source_function,Source_file,Source_line相关的开销信息
SWAPS:显示交换次数相关开销的信息

返回结果

converting HEAP to MyISAM:查询结果太大,内存都不够用了往磁盘上搬了。
Creating tmp table:创建临时表,mysql 先将拷贝数据到临时表,然后用完再将临时表删除
Copying to tmp table on disk:把内存中临时表复制到磁盘,危险!!!
locked:锁表

五、全局查询日志

  切莫在生产环境配置启用

在my.cnf中配置

# 开启
general_log=1
# 记录日志文件的路径
general_log_file=/path/logfile
# 输出格式
log_output=FILE

编码启用

set global general_log=1;
set global log_output='TABLE';

配置完成之后,将会记录到mysql库里的general_log表

select * from mysql.general_log;

总结

到此这篇关于MySQL查询截取的文章就介绍到这了,更多相关MySQL查询截取内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • 什么是大数据lambda架构
    一、什么是Lambda架构Lambda架构由Storm的作者[NathanMarz]提出,根据维基百科的定义,Lambda架构的设计是为了在处理大规模数 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 近年来,大数据成为互联网世界的新宠儿,被列入阿里巴巴、谷歌等公司的战略规划中,也在政府报告中频繁提及。据《大数据人才报告》显示,目前全国大数据人才仅46万,未来3-5年将出现高达150万的人才缺口。根据领英报告,数据剖析人才供应指数最低,且跳槽速度最快。中国商业结合会数据剖析专业委员会统计显示,未来中国基础性数据剖析人才缺口将高达1400万。目前BAT企业中,60%以上的招聘职位都是针对大数据人才的。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文介绍了在Hibernate配置lazy=false时无法加载数据的问题,通过采用OpenSessionInView模式和修改数据库服务器版本解决了该问题。详细描述了问题的出现和解决过程,包括运行环境和数据库的配置信息。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
  • 问题描述:域名已经备案,我全部都有,也在后台配置了,但是手机预览,还是请求失败,PC端是可以请求 ... [详细]
  • linux6.5 配置邮件服务,centos 6.5服务器搭建邮件服务postfix和dovecot
    centos6.5搭建邮件服务postfix和dovecot------------------------------------------------安装DNS指定邮件交换记 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
author-avatar
jinglongyy70
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有