常用的MySQL 优化方法

2023-11-10

数据库优化一方面是找出系统的瓶颈,提高MySQL数据库的整体性能,而另一方面需要合理的结构设计和参数调整,以提高用户的相应速度,同时还要尽可能的节约系统资源,以便让系统提供更大的负荷。
 
本文我们来谈谈项目中常用的MySQL优化方法,共19条,具体如下:

文章目录

一、EXPLAIN

做MySQL优化,我们要善用EXPLAIN查看SQL执行计划。

下面来个简单的示例,标注(1、2、3、4、5)我们要重点关注的数据:

在这里插入图片描述

  • type列,连接类型。一个好的SQL语句至少要达到range级别。杜绝出现all级别。
  • key列,使用到的索引名。如果没有选择索引,值是NULL。可以采取强制索引方式
  • key_len列,索引长度。
  • rows列,扫描行数。该值是个预估值。
  • extra列,详细说明。注意,常见的不太友好的值,如下:Using filesort,Using temporary。

二、SQL 语句中 IN 包含的值不应过多

MySQL对于IN做了相应的优化,即将IN中的常量全部存储在一个数组里面,而且这个数组是排好序的。但是如果数值较多,产生的消耗也是比较大的。再例如:select id from t where num in(1,2,3) 对于连续的数值,能用between就不要用in了;再或者使用连接来替换。

三、SELECT语句务必指明字段名称

SELECT*增加很多不必要的消耗(CPU、IO、内存、网络带宽);增加了使用覆盖索引的可能性;当表结构发生改变时,前断也需要更新。所以要求直接在select后面接上字段名。

四、当只需要一条数据的时候,使用limit 1

这是为了使EXPLAIN中type列达到const类型

五、如果排序字段没有用到索引,就尽量少排序

六、如果限制条件中其他字段没有索引,尽量少用or

or两边的字段中,如果有一个不是索引字段,而其他条件也不是索引字段,会造成该查询不走索引的情况。很多时候使用union all或者是union(必要的时候)的方式来代替“or”会得到更好的效果。

七、尽量用 union all 代替 union

union和union all的差异主要是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。当然,union all的前提条件是两个结果集没有重复数据。

八、不使用ORDER BY RAND()

select id from `dynamic` order by rand() limit 1000;

上面的SQL语句,可优化为:

select id from `dynamic` t1 join (select rand() * (select max(id) from `dynamic`) as nid) t2 on t1.id > t2.nidlimit 1000;

九、区分in和exists、not in和not exists

select * from 表A where id in (select id from 表B)

上面SQL语句相当于

select * from 表A where exists(select * from 表B where 表B.id=表A.id)

区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询。所以IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

关于not in和not exists,推荐使用not exists,不仅仅是效率问题,not in可能存在逻辑问题。如何高效的写出一个替代not exists的SQL语句?

原SQL语句:

select colname … from A表 where a.id not in (select b.id from B表)

高效的SQL语句:

select colname … from A表 Left join B表 on where a.id = b.id where b.id is null

取出的结果集如下图表示,A表不在B表中的数据:

在这里插入图片描述

十、使用合理的分页方式以提高分页的效率

select id,name from product limit 866613, 20

使用上述SQL语句做分页的时候,可能有人会发现,随着表数据量的增加,直接使用limit分页查询会越来越慢。

优化的方法如下:可以取前一页的最大行数的id,然后根据这个最大的id来限制下一页的起点。比如此列中,上一页最大的id是866612。SQL可以采用如下的写法:

select id,name from product where id> 866612 limit 20

十一、分段查询

在一些用户选择页面中,可能一些用户选择的时间范围过大,造成查询缓慢。主要的原因是扫描行数过多。这个时候可以通过程序,分段进行查询,循环遍历,将结果合并处理进行展示。

如下图这个SQL语句,扫描的行数成百万级以上的时候就可以使用分段查询:

在这里插入图片描述

十二、避免在 where 子句中对字段进行 null 值判断

对于null的判断会导致引擎放弃使用索引而进行全表扫描。

十三、不建议使用%前缀模糊查询

例如LIKE“%name”或者LIKE“%name%”,这种查询会导致索引失效而进行全表扫描。但是可以使用LIKE “name%”。

那如何查询%name%?

如下图所示,虽然给secret字段添加了索引,但在explain结果并没有使用:

在这里插入图片描述

那么如何解决这个问题呢,答案:使用全文索引。

在我们查询中经常会用到select id,fnum,fdst from dynamic_201606 where user_name like ‘%zhangsan%’; 。这样的语句,普通索引是无法满足查询需求的。庆幸的是在MySQL中,有全文索引来帮助我们。

创建全文索引的SQL语法是:

ALTER TABLE `dynamic_201606` ADD FULLTEXT INDEX `idx_user_name` (`user_name`);

使用全文索引的SQL语句是:

select id,fnum,fdst from dynamic_201606 where match(user_name) against('zhangsan' in boolean mode);

注意:在需要创建全文索引之前,请联系DBA确定能否创建。同时需要注意的是查询语句的写法与普通索引的区别。

十四、避免在 where 子句中对字段进行表达式操作

比如:

select user_id,user_project from user_base where age*2=36;

中对字段就行了算术运算,这会造成引擎放弃使用索引,建议改成:

select user_id,user_project from user_base where age=36/2;

十五、避免隐式类型转换

where子句中出现column字段的类型和传入的参数类型不一致的时候发生的类型转换,建议先确定where中的参数类型。

在这里插入图片描述

十六、对于联合索引来说,要遵守最左前缀法则

举列来说索引含有字段id、name、school,可以直接用id字段,也可以id、name这样的顺序,但是name;school都无法使用这个索引。所以在创建联合索引的时候一定要注意索引字段顺序,常用的查询字段放在最前面。

十七、必要时可以使用force index来强制查询走某个索引

有的时候MySQL优化器采取它认为合适的索引来检索SQL语句,但是可能它所采用的索引并不是我们想要的。这时就可以采用forceindex来强制优化器使用我们制定的索引。

十八、注意范围查询语句

对于联合索引来说,如果存在范围查询,比如between、>、<等条件时,会造成后面的索引字段失效。

在这里插入图片描述

LEFT JOIN A表为驱动表,INNER JOIN MySQL会自动找出那个数据少的表作用驱动表,RIGHT JOIN B表为驱动表。

注意:

1)MySQL中没有full join,可以用以下方式来解决:

select * from A left join B on B.name = A.namewhere B.name is nullunion allselect * from B;

2)尽量使用inner join,避免left join:

参与联合查询的表至少为2张表,一般都存在大小之分。如果连接方式是inner join,在没有其他过滤条件的情况下MySQL会自动选择小表作为驱动表,但是left join在驱动表的选择上遵循的是左边驱动右边的原则,即left join左边的表名为驱动表。

3)合理利用索引:

被驱动表的索引字段作为on的限制字段。

4)利用小表去驱动大表:

在这里插入图片描述

从原理图能够直观的看出如果能够减少驱动表的话,减少嵌套循环中的循环次数,以减少 IO总量及CPU运算的次数。

5)巧用STRAIGHT_JOIN:

inner join是由MySQL选择驱动表,但是有些特殊情况需要选择另个表作为驱动表,比如有group by、order by等「Using filesort」、「Using temporary」时。STRAIGHT_JOIN来强制连接顺序,在STRAIGHT_JOIN左边的表名就是驱动表,右边则是被驱动表。在使用STRAIGHT_JOIN有个前提条件是该查询是内连接,也就是inner join。其他链接不推荐使用STRAIGHT_JOIN,否则可能造成查询结果不准确。

在这里插入图片描述

这个方式有时能减少3倍的时间。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

常用的MySQL 优化方法 的相关文章

  • 使用Perl/DBI/MySQL/InnoDB查找外键信息

    我想以编程方式查找 MySQL 数据库中特定 InnoDB 表的外键 我正在使用 Perl 我偶然发现 dbh gt foreign key info 我刚刚尝试使用它 但似乎有点错误 它不会返回 ON DELETE 和 ON UPDATE
  • 如果 Row1 = 值 1,则更新其他行

    我有一个小的 php 脚本 用于访问 mySql 数据库 我想在数据库中插入新记录之前查看该数字 值 1 是否等于数据库中的记录 这也在第 1 行 所以我想 查看传入的电话号码是否等于数据库中的电话号码 如果是这样 则必须保持电话号码相同的
  • 无法在 Mac 上启动 MySQL

    使用 Brew 安装后 我无法运行 MySQL 我使用的是 OS X El Capitan 版本 10 11 3 和 MySQL Server 版本 5 7 11 当我启动服务器时 我收到 启动 MySQL 错误 服务器退出而不更新 PID
  • JDBC插入实数数组

    我试图将一个真实的数组插入到 postgresql 数组中 该表的定义是 String sqlTable CREATE TABLE IF NOT EXISTS ccmBlock sampleId INTEGER block REAL 插入内
  • 在 SQL Server 上执行分页的最佳方式是什么?

    我有一个数据库超过200万记录 我需要执行分页以在我的 Web 应用程序上显示 该应用程序每页必须有 10 条记录DataGrid 我已经尝试使用ROW NUMBER 但是这种方式会选择所有 200 万条记录 然后只得到 10 条记录 我也
  • 如何通过 SQL 表关联 SQL 中的实体

    我是数据库设计的初学者 我需要为项目创建数据库 我可以用面向对象的术语解释我想要做什么 值得庆幸的是 数据库专家会很友善地向我解释如何在数据库方面处理这个问题 我想创建一个与位置实体 州 城市 有关系的用户 ID 名称 实体 所以在编程语言
  • SQL Server 连接其他表中不存在的位置

    Service Asset AssetService Id Name Id Name AssetId ServiceId
  • Mysql用in语句限制

    我正在写一个查询 SELECT user bookmarks id as user bookmark id bookmark id user bookmarks user id bookmark url bookmark website b
  • 获取带有计数的不同记录

    我有一张桌子personid and msg列 personid msg 1 msg1 2 msg2 2 msg3 3 msg4 1 msg2 我想得到总计msg对于每个personid 我正在尝试这个查询 select distinct
  • 解析带下划线的 SQL Server 数字文字

    我想知道它为什么有效以及为什么它不返回错误 SELECT 2015 11 Result 11 2015 第二种情况 SELECT 2 1 a a 2 1 检查元数据 SELECT name system type name FROM sys
  • SQL查询查找表的主键?

    我怎样才能找到哪一列首要的关键使用查询来创建表 这是重复的question https stackoverflow com questions 893874 mysql determine tables primary key dynami
  • 如何使用 BigQuery 有效地选择另一个表中匹配子字符串的记录?

    我有一个包含数百万个字符串的表 我想将其与包含大约两万个字符串的表进行匹配 如下所示 standardSQL SELECT record FROM record JOIN fragment ON record name LIKE CONCA
  • 随机组合 MySQL 数据库中的两个单词

    我有一个包含名词和形容词的数据库 例如 id type word 1 noun apple 2 noun ball 3 adj clammy 4 noun keyboard 5 adj bloody ect 我想创建一个查询 它将抓取 10
  • 在 android 中建立与 MySQL 的池连接

    我需要从我的 Android 应用程序访问 MySQL 数据库 现在所有的工作都通过 DriverManager getConnection url 等等 但我必须从多个线程访问数据库 所以我必须使用连接池 问题1 是 com mysql
  • Spark SQL 中的 SQL LIKE

    我正在尝试使用 LIKE 条件在 Spark SQL 中实现联接 我正在执行连接的行看起来像这样 称为 修订 Table A 8NXDPVAE Table B 4 8 NXD V 在 SQL Server 上执行联接 A revision
  • mysql排序和排名语句

    我需要一些 mysql 语句的帮助 我的表 1 有 7 列 表 2 有 8 列 额外的列名为排名 我的语句应该是这样的 从表 1 中选择全部 然后按 用户数 排序 将其插入表 2 中并排名开始 1 2 3 等 table 1 usernam
  • 快速将列的副本添加到 MySQL 表

    我需要一种快速的方法来复制表中的 DATETIME 列并为其指定一个新名称 我的表中有一个名为 myDate 的列 名为 myResults 我需要一个查询来在名为 newDate 的表中创建一个新列 该列的数据与 myDate 列完全相同
  • 如何通过SQL查询检查是否有JSON函数?

    有SQL 2016 中的 JSON 函数 https learn microsoft com en us sql t sql functions json functions transact sql例如 JSON VALUE JSON Q
  • 如何部署“SQL Server Express + EF”应用程序

    这是我第一次部署使用 SQL Server Express 数据库的应用程序 我首先使用实体 框架模型来联系数据库 我使用 Install Shield 创建了一个安装向导来安装应用程序 这些是我在目标计算机中安装应用程序所执行的步骤 安装
  • post php mysql 的拆分关键字

    我有一个表存储帖子 ID 它的标签如下 Post id Tags 1 keyword1 keyword2 keyword3 我想循环遍历该表中的每一行并执行以下操作 将关键字1 关键字2 关键字3放入新表中 word id word val

随机推荐

  • Java相关注解

    标题 TableField Mybatis plus使用注解 TableField exist false 注明非数据库字段属性 TableField exist false 注解加载bean属性上 表示当前属性不是数据库字段 但项目中必须
  • vue3 父子组件传参详解

    前言 我引用了大佬的文章 但我实在找不到网址链接了 我记录在笔记上的 如果大佬看见了 麻烦给我说一下 我注明一下出处 建议先看son vue 里面写了那三种方式 首先放一个我的demo defineProps什么的父子传参api不用引入 直
  • 06 科技英语|控制与优化学科词汇

    maneuver n 策略 v 操控 调遣 manipulate vt 熟练控制 scalability n 可扩展性 leverage n 杠杆 v 促使 改变 flexibility n 弹性 dispatch n 急件 v 调度 派遣
  • extern关键字的用法知识点总结

    extern关键字的用法 编译C文件的步骤 数据类型及其长度 知识点总结 一 extern关键字的用法 extern关键字可以用来声明变量 函数作为外部变量或者函数供其它文件使用 extern表明变量或者函数是定义在其他其他文件中的 例如
  • 《Python编程:从入门到实践》第九章练习题

    Python编程 从入门到实践 第九章练习题 Python编程 从入门到实践 第九章练习题 9 1 餐馆 9 2 三家餐馆 9 3 用户 9 4 就餐人数 9 5 尝试登录次数 9 6 冰淇淋小店 9 7 管理员 9 8 权限 9 9 电瓶
  • python+selenium+PhantomJS爬取唯品会

    由于唯品会是利用js动态生成html作为反爬机制 所以不能用以前的爬取html的方法进行爬取 本程序是用selenium PhantomJS对唯品会进行爬取 可以根据需要输入要爬取的商品 还有爬取的起始页和结束页 程序代码以及注释的内容如下
  • vue[el-table]表格内附件上传、elementui 的http-request 上传附件,并且还可以传参数

    解决 通过http request
  • cmd 窗口 make clean process_begin: CreateProcess(NULL, rm Dynamics.o test.o, …) failed.

    CMD执行make clean报错 make clean rm Dynamics o test o process begin CreateProcess NULL rm Dynamics o test o failed make e 2
  • layui 弹出iframe选择数据并获取数据

    var layer layui layer layer open type 2 2表示弹出的是iframe 1表示弹出的是层 offset auto title 选择题目 font size 18px area 500px 300px sc
  • 华为HCIE云计算之IPsan存储裸设备映射给Linux主机

    华为HCIE云计算之IPsan存储裸设备映射给Linux主机 一 环境简介 1 Linux系统版本 2 各服务器IP地址 二 配置数据存储 1 登录华为V3数据存储 2 创建LUN 3 创建Lun组 4 创建主机 5 创建主机组 6 创建主
  • 行业轮动策略(思想+源码)

    一 行业轮动策略简介 行业轮动是利用市场趋势获利的一种主动量化投资交易策略 其本质是利用不同投资品种强势时间的错位对行业品种进行切换以达到投资收益最大化的目的 通俗点讲就是根据不同行业的区间表现差异 性进行轮动配置 力求能够抓住区间内表现较
  • yarn add报错error: Missing list of packages to add to your project.

    问题描述 运行yarn add命令安装全部依赖项报错 原因 yarn安装全部依赖是 yarn 或者 yarn install 不是yarn add这个命令 yarn add 后面需要跟具体的包名安装某个包 解决 更换成 yarn 或者 ya
  • DDR3详解(以Micron MT41J128M8 1Gb DDR3 SDRAM为例)之一

    1 结构框图 2 管脚功能描述 管脚符号 类型 描述 A0 A9 A10 AP A11 A12 BC A13 Input 地址输入 为ACTIVATE命令提供行地址 和为READ WRITE命令的列地址和自动预充电位 A10 以便从某个ba
  • 基于Selenium模块实现无界面模式 & 执行JS脚本

    此篇文章主要介绍如何使用 Selenium 模块实现 无界面模式 执行JS脚本 把滚动条拉到底部 并以具体的示例进行展示 1 Selenium 设置无界面模式 创建浏览器对象之前 创建 options 功能对象 options webdri
  • Qt 自动单元测试Auto Test Project详解

    Qt 自动单元测试Auto Test Project详解 有时 残缺也是一种美 测试 则意味着需要投入 有些项目的迭代周期很短 如果也搞一个 test 则可能性价比很低 Qt 自动单元测试Auto Test Project详解 官方 htt
  • Eigen矩阵运算库快速上手

    目录 1 配置 2 初始化 2 1 Array类 2 2 Vector类 2 3 Matrix类 2 4 Vector赋值 2 5 高级初始化 3 矩阵计算 3 1 矩阵基本计算 3 2 线性求解 3 3 特征值计算 3 4 奇异值分解 总
  • spring的自动装配三种模式

    第一种装配模式是我们非常熟悉的xml配置 这种装配需要写id class 还有这个类具体的属性值等等 较为麻烦 第二种byName和byType的自动装配模式 如何设置呢 我们有三个类 cat dog people 并且people种有ca
  • MATLAB进阶教程第一节(图形绘制)

    本节是matlab进阶教程的第一节 头一次看的小白请先看完我的matlab入门基础 方便消化 对那些急需图形绘制的朋友将会有很大帮助 一 二维图形的绘制 1 1plot函数 形式 plot X Y S X Y是向量 分别表示点集的横坐标和纵
  • c++基础十四(冒泡排序)

    冒泡排序 基本思路 对于一组要排序的元素列 依次比较相邻的两个数 将比较小的数放在前面 比较大的数放在后面 如此继续 直到比较到最后的两个数 将小数放在前面 大数放在后面 重复步骤 直至全部排序完成 例子 数组Num 5 9 6 7 3 1
  • 常用的MySQL 优化方法

    数据库优化一方面是找出系统的瓶颈 提高MySQL数据库的整体性能 而另一方面需要合理的结构设计和参数调整 以提高用户的相应速度 同时还要尽可能的节约系统资源 以便让系统提供更大的负荷 本文我们来谈谈项目中常用的MySQL优化方法 共19条