查询效率至少提高4倍的MySQL技巧

  • 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()
SELECTid 
FROM`dynamic` 
ORDER BYrand( ) LIMIT 1000;

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

SELECTid 
FROM`dynamic` t1JOIN ( SELECT rand( ) * ( SELECT max( id ) FROM `dynamic` ) AS nid ) t2 ON t1.id > t2.nid LIMIT 1000;
  • 区分in和exists、not in和not exists
SELECT* 
FROM表 A 
WHEREid IN ( SELECT id FROM 表 B )

上面SQL语句相当于

SELECT* 
FROM表 A 
WHEREEXISTS ( 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语句:

SELECTcolname … 
FROMA表 
WHEREa.id NOT IN (
SELECTb.id 
FROMB表)

高效的SQL语句:

SELECTcolname … 
FROMA表LEFT JOIN B表 ON 
WHEREa.id = b.id 
WHEREb.id IS NULL
  • 使用合理的分页方式以提高分页的效率
SELECTid,
NAME 
FROMproduct LIMIT 866613,20

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

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

SELECTid,
NAME 
FROMproduct 
WHEREid > 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语句是:

selectid,fnum,fdstfromdynamic_201606wherematch(user_name) against('zhangsan’inboolean mode);

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

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

比如:

SELECTuser_id,user_project 
FROMuser_base 
WHEREage * 2 = 36;

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

SELECTuser_id,user_project 
FROMuser_base 
WHEREage = 36 / 2;
  • 避免隐式类型转换

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

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

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

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

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

  • 注意范围查询语句

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

  • 关于JOIN优化

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

注意:

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

SELECTuser_id,user_project 
FROMuser_base 
WHEREage = 36 / 2;

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倍的时间。

以上MySQL优化方法希望对大家有所帮助!

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

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

相关文章

【免费题库】华为OD机试 - 根据IP查找城市(Java JS Python C C++)

须知 哈喽,本题库完全免费,收费是为了防止被爬,大家订阅专栏后可以私信联系退款。感谢支持 文章目录 须知题目描述输入描述输出描述解题思路:Java代码:JS代码:Python代码:C++代码:题目描述 某业务需要根据终端的IP地址获取该终端归属的城市,可以根据公开的IP地址池信…

Uipath用计划任务启动 bat脚本语句

方法一 cd C:\Program Files\UiPath\Studio UiRobot execute --file "Uipath路径\project.json" 这种是用UiRobot.exe来启动任务的 方法二 "C:\Progra~1\UiPath\Studio\UiRobot.exe" -file "C:\Users\Documents\UiPath\se_Windows.1.0.3.nupkg&q…

【前端】掌握按钮的显示与隐藏

目录 一、前言二、实现显示与隐藏的四种方式1、CSS属性控制2、JavaScript控制3、Vue.js响应式控制 三、需求背景四、代码实现1、定义变量2、绑定事件3、监听选中的学生4、返回return 五、整体效果1、没有勾选学生2、已勾选学生 六、设置按钮显示与隐藏的优势利弊1、优势2、劣势…

计算机网络面试问题

文章目录 1.DHCP协议:动态分配IP地址2.SNMP协议3.HTTP协议4.DNS协议1.DHCP协议:动态分配IP地址 (1)作用: DHCP服务器动态地将IP池里的IP地址分配给新加入网络的主机。基于4次UDP广播。 (2)DHCP的四种报文: 报文名源IP地址目的IP地址①DHCP发现报文 Discover0.0.0.0255.25…

MySQL慢查询怎么办?需要关注Explain的哪些关键字?

目录 1-引言&#xff1a;什么是慢查询1-1 慢查询定义1-2 为什么排查慢查询 2-核心&#xff1a;慢查询排查2-1 慢查询定位2-2 慢查询解决2-2-1 Explain 排查慢查询2-2-2 Explain 重点关键字 3-总结&#xff1a;慢查询知识点小结 1-引言&#xff1a;什么是慢查询 1-1 慢查询定义…

C# 字面量null对于引用类型变量✓和值类型变量×

编译器让相同的字符串字面量共享堆中的同一内存位置以节约内存。 在C#中&#xff0c;字面量&#xff08;literal&#xff09;是指直接表示固定值的符号&#xff0c;比如数字、字符串或者布尔值。而关键字&#xff08;keyword&#xff09;则是由编程语言定义的具有特殊含义的标…

微信小程序实现腾讯地图

1、// map.js Page({ data: { latitude: 0, // 初始纬度值 longitude: 0, // 初始经度值 markers: [] }, onReady: function (e) { this.getLocation(); // 主动获取用户地理位置信息 }, getLocation: function () { wx.getLocation({ type: gcj02, success: (res) > { thi…

羊大师解读,春季羊奶VS夏季羊奶

羊大师解读&#xff0c;春季羊奶VS夏季羊奶 夏季的羊奶和春季的羊奶在营养成分上并没有本质的区别&#xff0c;都含有丰富的蛋白质、矿物质和维生素等。然而&#xff0c;由于季节和气候的变化&#xff0c;人们饮用羊奶的需求和效果可能会有所不同。 在夏季&#xff0c;天气炎热…

C语言 | Leetcode C语言题解之第35题搜索插入位置

题目&#xff1a; 题解&#xff1a; int searchInsert(int* nums, int numsSize, int target) {int left 0, right numsSize - 1, ans numsSize;while (left < right) {int mid ((right - left) >> 1) left;if (target < nums[mid]) {ans mid;right mid - …

R语言 数据的整理与清洗(第一篇)

《Cookbook for R》 Manipulating Data ~ General Sorting 排序 1、vectors 向量 # 先随机生成一组向量 v <- sample(101:110)# 排序sort() sort(v) #> [1] 101 102 103 104 105 106 107 108 109 110# 反向排序 sort(v, decreasingTRUE) #> [1] 110 109 108 107 1…

Docker容器的使用与操作

1、什么是容器 镜像和容器的关系&#xff0c;就像是面向对象程序设计中的类和实例一样&#xff0c;镜像是静态的定义&#xff0c;容器是镜像运行时的实体&#xff0c;基于同一镜像可以创建若干个不同的容器。 每个容器都有一个软件镜像。可以将容器看作一个将应用程序及其依赖环…

使用vue3+ts+vite从零开始搭建bolg(二)

二、全局变量 2.1element-ui集成 pnpm i element-plus pnpm i element-plus element-plus/icons-vue main.ts配置文件 import ElementPlus from element-plus import element-plus/dist/index.css //ts-ignore import zhCn from element-plus/dist/locale/zh-cn.mjsapp.use…

浅说深度优先搜索(中)——回溯

写在最前 相信在你们不懈的努力之下&#xff0c;基本的递归一定可以写出来了&#xff0c;那么我们现在就来看看递归的升级版——回溯怎么写吧&#xff01; 简说回溯 递归是一种特别重要的解题策略。大部分题目需要找到最优解&#xff0c;而这个求解过程可能存在一定的规律性…

用单片机的矩阵键盘选择显示什么图像

注意行数据不能二进制 #include "reg51.h"typedef unsigned int u16; //对系统默认数据类型进行重定义 typedef unsigned char u8;//定义74HC595控制管脚 sbit SRCLKP3^6; //移位寄存器时钟输入 sbit RCLKP3^5; //存储寄存器时钟输入 sbit SERP3^4; //串行数据输入…

UE5(基础动作)多人游戏制作蹲伏

1.创建输入操作&#xff0c;IA_Crouch 在输入映射中添加 IA_Crouch,在触发器中创建两个索引&#xff0c;已按下已松开来创建蹲伏输入。 蹲伏操作必须要勾选角色-角色移动-crouch勾选可蹲伏否则你的人物无法真正蹲下。 为蹲伏创建函数&#xff0c;创建布尔来判断是否蹲伏。 通过…

CodeGemma初探

什么是 CodeGemma CodeGemma是一系列强大而轻量级的模型的集合&#xff0c;可以执行各种编码任务&#xff0c;包括填充中间代码补全、代码生成、自然语言理解、数学推理和指令跟随。 版本&#xff1a; instruct&#xff1a;7B, 这个版本专门针对自然语言到代码聊天和指令跟随…

day83 AJAX

1什么是AJAX AJAX语法 AJAX Asynchronous JavaScript and XML 异步js和XML 实现页面某一部份更新&#xff0c;无需服务器转发或重定向 1 $.ajax() 语法: $.ajax( { "url" : "url&qu…

数据库主从复制

一、主从复制概述 1、介绍&#xff1a; 主从复制是指将主数据库的 DDL 和 DML 操作写入到二进制日志中&#xff0c;将二进制日志传送到从库服务器&#xff0c;然后在从库上对这些日志重新执行&#xff08;重做&#xff09;&#xff0c;从而使得从库和主库的数据保持同步。 M…

百面算法工程师 | 分类网络总结

欢迎大家订阅我的专栏一起学习共同进步&#xff0c;主要针对25届应届毕业生 祝大家早日拿到offer&#xff01; lets go http://t.csdnimg.cn/dfcH3 目录 4. 经典分类网络与发展 4.1 AlexNet 4.2 VGGNet 4.3 GoogLeNet Inception 4.4 ResNet 4.5 DenseNet 4.6 MobileN…