您现在的位置是:网站首页> 编程资料编程资料

MySQL提升大量数据查询效率的优化神器_Mysql_

2023-05-26 578人已围观

简介 MySQL提升大量数据查询效率的优化神器_Mysql_

前言

在应用的的开发过程中,由于初期数据量小,开发人员写 SQL 语句时更重视功能上的实现,但是当应用系统正式上线后,随着生产数据量的急剧增长,很多 SQL 语句开始逐渐显露出性能问题,对生产的影响也越来越大,此时这些有问题的 SQL 语句就成为整个系统性能的瓶颈,因此我们必须要对它们进行优化.

为什么这么说呢?因为在MySQL查询语句中,语法比较的通用吗,要想得到一个数据集可以使用不同的查询语句!

例如我们需要查询一个数据表有多少行数据集?

1、暴力搜索

select count(*) from data;

这样虽然也可以达到效果,但是用 "SELECT * " 数据库需要解析更多的对象、字段、权限、属性等相关内容,在 SQL 语句复杂,硬解析较多的情况下,会对数据库造成沉重的负担。

增大网络开销,* 有时会误带上如log、IconMD5之类的无用且大文本字段,数据传输size会几何增长。特别是MySQL和应用程序不在同一台机器,这种开销非常明显。

2、限定字段查询

select count(id) from data;

这里的id是一个递增的序列,查询效果确实有所提升。

MySQL的优化方式有很多,大致我们可以从以下几点来优化MySQL:

  • 从设计上优化
  • 从查询上优化
  • 从索引上优化
  • 从存储上优化

查看SQL执行频率

MySQL 客户端连接成功后,通过 show [session|global] status 命令可以查看服务器状态信息。通过查看状态信息可以查看对当前数据库的主要操作类型。

--下面的命令显示了当前 session 中所有统计参数的值 show session status like 'Com_______'; -- 查看当前会话统计结果 show global status like 'Com_______'; -- 查看自数据库上次启动至今统计结果 show status like 'Innodb_rows_%'; -- 查看针对Innodb引擎的统计结果

 定位低效率执行SQL

可以通过以下两种方式定位执行效率较低的 SQL 语句。

慢查询日志 : 通过慢查询日志定位那些执行效率较低的 SQL 语句。

show processlist:该命令查看当前MySQL在进行的线程,包括线程的状态、是否锁表等,可以实时地查看 SQL 的执行情况,同时对一些锁表操作进行优化。

-- 查看慢日志配置信息 show variables like '%slow_query_log%'; -- 开启慢日志查询 set global slow_query_log=1; -- 查看慢日志记录SQL的最低阈值时间 show variables like 'long_query_time%'; -- 修改慢日志记录SQL的最低阈值时间 set global long_query_time=4;
show processlist;

  • 1) id列,用户登录mysql时,系统分配的"connection_id",可以使用函数connection_id()查看
  • 2) user列,显示当前用户。如果不是root,这个命令就只显示用户权限范围的sql语句
  • 3) host列,显示这个语句是从哪个ip的哪个端口上发的,可以用来跟踪出现问题语句的用户
  • 4) db列,显示这个进程目前连接的是哪个数据库
  • 5) command列,显示当前连接的执行的命令,一般取值为休眠(sleep),查询(query),连接(connect)等
  • 6) time列,显示这个状态持续的时间,单位是秒
  • 7) state列,显示使用当前连接的sql语句的状态,很重要的列。state描述的是语句执行中的某一个状态。一个sql语句,以查询为例,可能需要经过copying to tmp table、sorting result、sending data等状态才可以完成
  • 8) info列,显示这个sql语句,是判断问题语句的一个重要依据

explain分析执行计划

通过以上步骤查询到效率低的 SQL 语句后,可以通过 EXPLAIN命令获取 MySQL如何执行 SELECT 语句的信息,包括在 SELECT 语句执行过程中表如何连接和连接的顺序。

-- 准备测试数据 create database mydb13_optimize; use mydb13_optimize;

执行sql脚本sql_optimize.sql添加数据

explain select * from user where uid = 1;

 id 字段是 select查询的序列号,是一组数字,表示的是查询中执行select子句或者是操作表的顺序。id 情况有三种:

1、id 相同表示加载表的顺序是从上到下

explain select * from user u, user_role ur, role r where u.uid = ur.uid and ur.rid = r.rid ;

2、 id 不同id值越大,优先级越高,越先被执行。

explain select * from role where rid = (select rid from user_role where uid = (select uid from user where uname = '张飞'))

3、 id 有相同,也有不同,同时存在。id相同的可以认为是一组,从上往下顺序执行;在所有的组中,id的值越大,优先级越高,越先执行。

  表示 SELECT 的类型,常见的取值,如下表所示:

type 显示的是访问类型,是较为重要的一个指标,可取值为:  

结果从最到最坏以此:system > const > eq_ref > ref > range > index > ALL 

其他的额外的执行计划信息,在该列展示 。

 Mysql从5.0.37版本开始增加了对 show profiles 和 show profile 语句的支持。show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。

通过 have_profiling 参数,能够看到当前MySQL是否支持profile:

select @@have_profiling; set profiling=1; -- 开启profiling 开关;

 通过profile,我们能够更清楚地了解SQL执行的过程。首先,我们可以执行一系列的操作

show databases; use mydb13_optimize; show tables; select * from user where id < 2; select count(*) from user;

执行完上述命令之后,再执行show profiles 指令, 来查看SQL语句执行的耗时:

show profiles;

 通过show  profile for  query  query_id 语句可以查看到该SQL执行过程中每个线程的状态和消耗的时间:

show profile for query 8;

 在获取到最消耗时间的线程状态后,MySQL支持进一步选择all、cpu、block io 、context switch、page faults等明细类型类查看MySQL在使用什么资源上耗费了过高的时间。例如,选择查看CPU的耗费时间  :

show profile cpu for query 133;

 在获取到最消耗时间的线程状态后,MySQL支持进一步选择all、cpu、block io 、context switch、page faults等明细类型类查看MySQL在使用什么资源上耗费了过高的时间。例如,选择查看CPU的耗费时间  :

trace分析优化器执行计划

MySQL5.6提供了对SQL的跟踪trace, 通过trace文件能够进一步了解为什么优化器选择A计划, 而不是选择B计划

SET optimizer_trace="enabled=on",end_markers_in_json=on; set optimizer_trace_max_mem_size=1000000;

 执行SQL语句 :

select * from user where uid < 2;

最后, 检查information_schema.optimizer_trace就可以知道MySQL是如何执行SQL的 :

select * from information_schema.optimizer_trace\G;

使用索引优化

索引是数据库优化最常用也是最重要的手段之一, 通过索引通常可以帮助用户解决大多数的MySQL的性能优化问题。

create table `tb_seller` ( `sellerid` varchar (100), `name` varchar (100), `nickname` varchar (50), `password` varchar (60), `status` varchar (1), `address` varchar (100), `createtime` datetime, primary key(`sellerid`) );

 索引是数据库优化最常用也是最重要的手段之一, 通过索引通常可以帮助用户解决大多数的MySQL的性能优化问题。

insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('alibaba','阿里巴巴','阿里小店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00'); insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('baidu','百度科技有限公司','百度小店','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00'); insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('huawei','华为科技有限公司','华为小店','e10adc3949ba59abbe56e057f20f883e','0','北京市','2088-01-01 12:00:00'); insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('itcast','传智播客教育科技有限公司','传智播客','e10adc3949ba59abbe56e057f20f883e','1','北京市','2088-01-01 12:00:00'); insert into `tb_seller` (`sellerid`, `name`, `nickname`, `password`, `status`, `address`, `createtime`) values('itheima','黑马程序员','黑马程序员','e10adc3949ba59abbe56e057f20f883e','0','北京市','2088-01-01 12:00:00'); insert into `tb_seller` (`sellerid`, `name`, `nickname`, `p
                
                

-六神源码网