MySQL的优化

优化MySQL的几点:

从设计上优化

从查询上优化

从索引上优化

从存储上优化

1,SQL的执行频率

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

参数含义
Com_select执行select操作的次数,一次查询只累加1
Com_insert执行INSERT 操作的次数,对于批量插入的 INSERT操作,只累加一次
Com_update执行UPDATE 操作的次数
Com_delete执行DELETE 操作的次数
Innodb_rows_readselect查询返回的行数
Innodb_rows_inserted执行INSERT操作插入的行数
Innodb_rows_updated执行UPDATE 操作更新的行数
Innodb_rows_deleted执行DELETE 操作删除的行数
Connections试图连接 MySQL服务器的次数
Uptime服务器工作时间
Slow_queries慢查询的次数
-- 查看当前会话SQL执行类型的统计信息
show session status like 'Com_______';-- 7个_-- 查看全局会话SQL执行类型的统计信息(自从上次MySQL服务器启动至今)
show global status like 'Com_______';-- 查看针对InnoDB引擎的统计信息
show status like 'Innodb_rows_%';

2,定位低效率执行SQL

方式:

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

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

(1)慢日志查询

-- 查询慢查询日志配置信息
show variables like 'slow_query_log%';-- 开启慢查询日志
set global slow_query_log=1;-- 查看慢查询日志的最低时间 查询大于等于10秒的会记录
show variables like 'long_query_time%';-- 修改最低时间
set global long_query_time=5;

(2)show processlist

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列,显示使用当前连接的sq语句的状态,很重要的列。state描述的是语句执行中的某一个状态。一个sqi语句,以查询为例,可能需要经过copying to tmp table、sorting result、sending data等状态才可以完成

8)info列,显示这个sql语句,是判断问题语句的一个重要依据

3,explain分析执行计划

字段含义
idselect查询的序列号,是一组数字,表示的是查询中执行select子句或者是操作表的顺序
select_type表示SELECT的类型,常见的取值有SIMPLE(简单表,即不使用表连接或者子查询)、PRIMARY(主查询,即外层的查询)、UNION (UNION中的第二个或者后面的查询语句)、SUBQUERY(子查询中的第一个SELECT)等
table输出结果集的表
type表示表的连接类型,性能由好到差的连接类型为( system .> const .……eq_ref ….ref ..…ref_or_null--> index_merge ---> index_subquery--> range ---…-> index ---> all)
possible_keys表示查询时。可能使用的索引
key表示实际使用的索引
key_len索引字段的长度
rows扫描行的数量
extra执行情况的说明和描述
-- 查询执行计划
explain select * from user where uid=1;-- 查询执行计划
explain select * from user where uname='张飞';

(1)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越大,优先级越高,越先被执行
explain select * from role where rid =(select rid from user_role where uid=(select uid from user where uname='张飞'));-- 3、id相同,也有不同,同时存在,id相同可认为是一组,从上往下顺序:在所有组中,id值越大,优先级越高,越先执行
explain select * from role r,(select * from user_role ur where ur.uid =(select uid from user where uname ='张飞')) t where r.rid=t.rid;

(2)select_type

select_type含义
SIMPLE简单的select查询,查询中不包含子查询或者UNION
PRIMARY查询中若包含任何复杂的子查询,最外层查询标记为该标识
SUBQUERY在SELECT或WHERE列表中包含了子查询
DERIVED在FROM列表中包含的子查询,被标记为DERIVED(衍生)MYSQL会递旧执行这些子查询,把结果放在临时表中
UNION若第二个SELECT出现在UNION之后,则标记为UNION;若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED
UNION  RESULT从UNION表获取结果的SELECT
explain select * from user;-- SIMPLE
explain select * from user u,user_role ur where u.uid=ur.uid;--SIMPLEexplain select * from role where rid =(select rid from user_role where uid=(select uid from user where uname='张飞'));-- PRIMARYexplain select * from role where rid =(select rid from user_role where uid=(select uid from user where uname='张飞'));-- SUBQUERYexplain select *from (select * from user limit 2) t;-- DERIVEDexplain select * from user where uid=1 union select * from user where uid=3;-- UNION/UNION  RESULT

(3)type

type含义
NULLMySQL不访问任何表,索引,直接返回结果
system系统表,少量数据,往往不需要进行磁盘IO;如果是5.7及以上版本的话就不是system了,而是all,即使只有一条记录
const命中主键(primary key)或者唯一(unique)索引;被连接的部分是一个常量(const)值;
eq_ref

对于前表的每一行,后表只有一行被扫描。(1) join查询;(2)命中主键(primary key)或者非空唯一(unique not null)索引;(3)等值连接;

左表有主键,而且左表的每一行和右表的每一行刚好匹配

ref

非唯一性索引扫描,返回匹配某个单独值的所有行。对于前表的每一行(row),后表可能有多于一行的数据被扫描

左表是普通索引,和右表匹配时可能会匹配多行

range只检索给定返回的行,使用一个索引来选择行。where之后出现 between ,< , > , in等操作
index需要扫描索引上的全部数据
all全表扫描,此时id上无索引

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

explain select * from user;-- typeexplain select now();-- NULL explain select * from mysql.tables_priv;-- system 查询系统表explain select * from user where uid=2;-- const
create unique index index_uname on user(uname);-- 添加普通索引
explain select * from user where uname='张飞';-- const
drop index index_uname on user;explain select * from user where uid>2;-- rangerexplain select uid from user;-- indexexplain select * from user;-- ALL

(4)table

显示这一步所访问数据库中表名称有时不是真实的表名字,可能是简称

(5)rows

扫描行的数量

(6)key

possible_keys:显示可能应用在这张表的索引,一个或多个

key :实际使用的索引,如果为NULL,则没有使用索引

key_len:表示索引中使用的字节数,该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下,长度越短越好

(7)extra

extra含义
using filesort说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取,称为“文件排序",效率低
using temporary需要建立临时表(temporary table)来暂存中间结果,常见于order by和group by;效率低
using indexSOL所需要返回的所有列数据均在一棵索引树上,避免访问表的数据行,效率不错

4,show file分析SQL

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

select @@have_profiling;

set profiling=1; -- 开启profiling开关

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

show profiles; 

show profiles;-- 查看每条时间
show profile for query 154;-- 查看cup耗费时间
show profile cpu for query 154;

5,trace优化器

打开trace,设置格式为JSON,并设置trace最大能够使用的内存大小,避免解析过程中因为默认内存过小而不能够完整展示

SET optimizer_trace="enabled=on" , end_markers_in_json=on;

set optimizer_trace_max_mem_size=1000000;

select * from information_schema.optimizer_trace \G;

6,索引优化

(1)全值匹配

和字段匹配即可,和字段无关

-- 全值匹配
explain select * from tb_seller where name='华为' and status='0' and address='北京市';

(2)最左前缀法

如果索引有多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始,并且不跳过索引中的列

-- 最左前缀法
-- 如果索引有多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始,并且不跳过索引中的列
explain select * from tb_seller where name='华为';-- 403explain select * from tb_seller where name='华为' and status='0';-- 410
explain select * from tb_seller where status='0' and name='华为';-- 410-- 违法最左前缀法,索引失效
explain select * from tb_seller where status='0';-- 跳跃一个,只有最左端索引失效
explain select * from tb_seller where name='华为' and address='北京市';-- 403

(3)其他匹配原则

范围查询右边的列,不能使用索引

-- 根据前面的两个字段name , status查询是走索引的,但是最后一个条件address没有用到索引
explain select * from tb_seller where name='华为' and status>'1' and address='北京市';-- 不要在索引列上进行运算操作,索引将失效
explain select * from tb_seller where substring(name,3,2)='科技';-- 字符串不加单引号,索引失效
explain select * from tb_seller where name='华为' and status=0;
extra解释
using index使用索引覆盖就会出现
using where在查找使用索引的情况下,需要回表去查询所需的数据
using index condition查找使用了索引,但是需要回表查询数据
using index,using where查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据
-- 尽量使用覆盖索引,避免使用select *
explain select * from tb_seller where name='华为' and address='北京市';-- 效率低
-- 从索引树中获得所有数据
explain select name from tb_seller where name='华为' and address='北京市';-- 效率高
explain select name,status,password from tb_seller where name='华为' and address='北京市';-- 效率低

1,用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到

2,以%开头的Like模糊查询,索引失效。——》弥补不足:不用*,使用索引列

3,如果MySQL评估使用索引比全表更慢,则不使用索引(由数据本身决定)

4,is NULL , is NOT NULL有时有效,有时索引失效(数据少的一方用索引)

5,in走索引,not in索引失效

6,单列索引和复合索引,尽量使用符合索引(如果一张表有多个单列索引,即使where中都使用了这些索引列,则只有一个最优索引生效)

7,SQL优化

(1)大批插入数据

1)主键顺序插入

因为InnoDB类型的表是按照主键的顺序保存的,所以将导入的数据按照主键的顺序排列,可以有效的提高导入数据的效率。如果innoDB表没有主键,那么系统会自动默认创建一个内部列作为主键,所以如果可以给表创建一个主键,将可以利用这点,来提高导入数据的效率

通过load向表加载数据时,保持主键有序,提高效率

主键有序时间<<主键无序时间

-- 1、首先,检查一个全局系统变量 'local_infile' 的状态, 如果得到如下显示 Value=OFF,则说明这是不可用的
show global variables like 'local_infile';-- 2、修改local_infile值为on,开启local_infile
set global local_infile=1;

2)关闭唯一性校验

在导入数据前执行SET UNIQUE_CHECKS=O,关闭唯一性校验,在导入结束后执行SETUNIQUE_CHECKS=1,恢复唯一性校验,可以提高导入的效率。

(2)insert优化

1,如果需要同时对一张表插入很多行数据时,应该尽量使用多个值表的insert语句,这种方式将大大的缩减客户端与数据库之间的连接、关闭等消耗。使得效率比分开执行的单个insert语句快

2,在事务中进行数据插入

3,数据有序插入

(3)order by优化

1)两种排序方式

第一种是通过对返回数据进行排序,也就是通常说的filesort排序,所有不是通过索引直接返回排序结果的排序都叫FileSort 排序

第二种通过有序索引顺序扫描直接返回有序数据,这种情况即为using index,不需要额外排序,操作效率高

-- 创建组合索引
create index idx_emp_age_salary on emp(age,salary);-- 排序,order by
explain select * from emp order by age;        -- Using filesort
explain select * from emp order by age,salary; -- Using filesortexplain select id from emp order by age;  -- Using index
explain select id,age from emp order by age;  -- Using index
explain select id,age,salary,name from emp order by age;  -- Using filesort-- order by后边的多个排序字段要求尽量排序方式相同
explain select id,age from emp order by age asc, salary desc;  -- Using index; Using filesort
explain select id,age from emp order by age desc, salary desc;  -- Backward index scan; Using index-- order by后边的多个排序字段顺序尽量和组合索引字段顺序一致
explain select id,age from emp order by salary,age; -- Using index; Using filesort

 2)Filesort优化

通过创建合适的索引,能够减少Filesort的出现,但是在某些情况下,条件限制不能让Filesort消失,那就需要加快Filesort的排序操作。对于Filesort , MySQL有两种排序算法:

1)两次扫描算法:MySQL4.1之前,使用该方式排序。首先根据条件取出排序字段和行指针信息,然后在排序区sort bufer中排序,如果sort buffer不够,则在临时表temporary table中存储排序结果。完成排序之后,再根据行指针回表读取记录,该操作可能会导致大量随机/O操作

2)一次扫描算法:一次性取出满足条件的所有字段,然后在排序区sort buffer 中排序后直接输出结果集。排序时内存开销较大,但是排序效率比两次扫描算法要高

MysQL通过比较系统变量 max_length_for_sort_data的大小和Query语句取出的字段总大小,来判定是否那种排序算法,如果max_length_for_sort_data更大,那么使用第二种优化之后的算法;否则使用第一种

可以适当提高sort_buffer_size和max_length_for_sort_data 系统变量,来增大排序区的大小,提高排序的效率

(4)子查询优化

使用子查询可以一次性的完成很多逻辑上需要多个步骤才能完成的sQL操作,同时也可以避免事务或者表锁死,并且写起来也很容易。但是,有些情况下,子查询是可以被更高效的连接(JoIN)替代

explain select * from user where uid in (select uid from user_role );

explain select * from user u join user_role ur on u.uid=ur.uid;

连接(Join)查询之所以更有效率一些,是因为MySQL不需要在内存中创建临时表来完成这个逻辑上需要两个步骤的查询工作

(5)limit优化

方法一:

在索引上完成排序分页操作,最后根据主键关联回原表查询所需要的其他列内容

explain select * from tb_user limit 900000,10;explain select * from tb_user a,(select id from tb_user order by id limit 900000,10) b where a.id=b.id;

方法二:

该方案适用于主键自增的表,可以把Limit查询转换成某个位置的查询

explain select * from tb_user where id>900000 limit 10;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/671069.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【01】判断素数/质数(C语言)

目录 &#xff08;1&#xff09;素数特点&#xff1a;只能被1和本身整除 &#xff08;2&#xff09;代码如下&#xff1a; &#xff08;3&#xff09;运行结果如下 ​编辑 &#xff08;4&#xff09;函数引申 &#xff08;1&#xff09;素数特点&#xff1a;只能被1和本身…

数字图像处理(实践篇)四十三 OpenCV-Python 使用SURF算法检测图像上的特征点的实践

目录 一 SURF算法概述 1 积分图 2 SURF算法 3 SIFT与SURF 二 涉及的函数 三 实践 一 SURF算法概述

在容器中使用buildah构建镜像

简介 buildah是一个构建OCI标准镜像的工具&#xff0c;可以用来替代docker build 在常见的linux发行版中可直接通过包管理工具安装使用 # centos yum install buildah# ubuntu/debian apt install buildah# alpine apk add buildah其他发行版安装方法详见 github&#xff0c…

Django通过Json配置文件分配多个定时任务

def load_config():with open("rule.json", rb)as f:config json.load(f)return configdef job(task_name, config, time_interval):# ... 通过task_name判断进行操作if task_name get_data_times:passdef main():config load_config()for task_name, task_value…

C++——stack与queue与容器适配器

1.stack和queue的使用 1.1stack的使用 栈这种数据结构我们应该挺熟了&#xff0c;先入后出&#xff0c;只有一个出口(出口靠栈顶近)嘛 stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类&#xff0c;这些容器类应该支持以操作&#xff1a; empty&#xff1…

专业知识库:中小型企业必备的高效工具

在如今这个信息爆炸的时代&#xff0c;知识管理已经成为了企业运营的重要环节。特别是对于中小型企业来说&#xff0c;如何有效地管理公司内部的知识&#xff0c;提高工作效率&#xff0c;已经成为了一个亟待解决的问题。在这篇文章中&#xff0c;我将向大家介绍一种能够帮助企…

Python轴承故障诊断入门教学

目录 往期精彩内容&#xff1a; 1 工作室实验平台介绍 2 轴承故障诊断教程—数据集 3 轴承故障诊断教程—算法模型 3.1 振动分析方法 3.2 频域特征提取 3.3 时域特征提取 3.4 模型基础的机器学习方法 3.5 深度学习方法 3.6 时频域融合方法 3.7 信号重构方法 3.8 基…

Linux-----文本三剑客补充~

一、模糊匹配 模糊匹配用 ~ 表示包含&#xff0c;!~表示不包含 1、匹配含有root的列 [rootlocalhost ~]#awk -F: /root/ /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [rootlocalhost ~]#awk -F: $1~ /root/ /etc/passw…

知名开发工具RubyMine全新发布v2023.3——支持AI Assistant

RubyMine 是一个为Ruby 和 Rails开发者准备的 IDE&#xff0c;其带有所有开发者必须的功能&#xff0c;并将之紧密集成于便捷的开发环境中。 RubyMine v2023.3正式版下载 新版本改进AI Assistant支持、Rails应用程序和引擎的自定义路径、对Rails 7.1严格locals的代码洞察、RB…

人胰岛素样生长因子-1 ELISA试剂盒IGF-1 (human), ELISA kit

高灵敏ELISA试剂盒&#xff0c;4小时内可得结果&#xff0c;最低可检测34.2 pg/ml的IGF-1 胰岛素样生长因子-1&#xff08;IGF-1&#xff09;是一种多肽激素&#xff0c;在结构上与胰岛素相似。它参与调节中枢和周围神经系统的神经元生长和发育。IGF-1是一种有效的神经元凋亡抑…

【Zookeeper】what is Zookeeper?

官网地址&#xff1a;https://zookeeper.apache.org/https://zookeeper.apache.org/ 以下来自官网的介绍 ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. A…

机试复习-3

前言&#xff1a;前面耽误太多时间&#xff0c;2月份是代码月&#xff0c;一定抓紧赶上&#xff0c;每天至少两道题 day1 2024.2.6 1.排序开启&#xff1a; 1.机试考试&#xff1a;排序应用考察 c的qsort c的sort 作用&#xff1a;对数组&#xff0c;vector排序&#…

c#读取csv文件中的某一列的数据

chat8 (chat779.com) 上面试GPT-3.5,很好的浏览网站&#xff0c;输入问题&#xff0c;可得到答案。 问题1&#xff1a;c#如何在csv中读取某一列数据 解答方案&#xff1a;在 C#中&#xff0c;你可以使用File.ReadAllLines来读取CSV中的所有行&#xff0c;然后逐行解析每一行…

flask+vue+python跨区通勤人员健康体检预约管理系统

跨区通勤人员健康管理系统设计的目的是为用户提供体检项目等功能。 与其它应用程序相比&#xff0c;跨区通勤人员健康的设计主要面向于跨区通勤人员&#xff0c;旨在为管理员和用户提供一个跨区通勤人员健康管理系统。用户可以通过系统及时查看体检预约等。 跨区通勤人员健康管…

Linux 分析指定JAVA服务进程所占内存CPU详情

1、获取服务进程PID [rootVM-32-26-centos ~]# service be3Service status Application is running as root (UID 0). This is considered insecure. Running [25383]2、获取进程占用详情 [rootVM-32-26-centos ~]# cat /proc/25383/status Name: java Umask: 0022 State: S…

Linux 文件比较工具

在Linux系统中&#xff0c;文件比较是一种常见的任务&#xff0c;用于比较两个文件之间的差异。文件比较可以帮助我们找出两个文件的不同之处&#xff0c;或者确定它们是否完全相同。在Linux中&#xff0c;有多种方法可以进行文件比较。 1. diff 在Linux中&#xff0c;diff命…

啤酒:精酿啤酒与冷盘的清新搭配

在夏日的傍晚&#xff0c;当太阳逐渐西沉&#xff0c;微风轻轻拂过&#xff0c;与亲朋好友围坐在一起&#xff0c;享受Fendi Club啤酒与冷盘的清新搭配&#xff0c;无疑是一种生活的享受。这两者的结合&#xff0c;不仅为味蕾带来了全新的体验&#xff0c;更为我们带来了片刻的…

24、数据结构/排序相关练习20240206

一、现有无序序列数组为{23,24,12,5,33,5,34,7}&#xff0c;请使用以下排序实现编程。 函数1&#xff1a;请使用冒泡排序实现升序排序 函数2&#xff1a;请使用简单选择排序实现升序排序 函数3&#xff1a;请使用快速排序实现升序排序 函数4&#xff1a;请使用插入排序实现…

记录 | linux下切换python版本

查看系统中存在的 python 版本 ls /usr/bin/python* 查看系统默认的 python 版本 python --version

《Git 简易速速上手小册》第3章:分支管理(2024 最新版)

文章目录 3.1 创建与合并分支3.1.1 基础知识讲解3.1.2 重点案例&#xff1a;为 Python 项目添加新功能3.1.3 拓展案例 1&#xff1a;使用 Pull Requests (PRs) 在团队中合作3.1.4 拓展案例 2&#xff1a;解决合并冲突 3.2 分支策略的最佳实践3.2.1 基础知识讲解3.2.2 重点案例&…