MySQL如何进行Sql优化

news2024/12/24 2:09:09

(1)客户端发送一条查询语句到服务器;

(2)服务器先查询缓存,如果命中缓存,则立即返回存储在缓存中的数据;

(3)未命中缓存后,MySQL通过关键字将SQL语句进行解析,并生成一颗对应的解析树,MySQL解析器将使用MySQL语法进行验证和解析。

​ 例如,验证是否使用了错误的关键字,或者关键字的使用是否正确;

(4)预处理是根据一些MySQL规则检查解析树是否合理,比如检查表和列是否存在,还会解析名字和别名,然后预处理器会验证权限;

​ 根据执行计划查询执行引擎,调用API接口调用存储引擎来查询数据;

(5)将结果返回客户端,并进行缓存;

SQL语句性能优化常用策略

1、 为 WHERE 及 ORDER BY 涉及的列上建立索引

对查询进行优化,应尽量避免全表扫描,首先应考虑在 WHERE 及 ORDER BY 涉及的列上建立索引。

2、where中使用默认值代替null 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断,创建表时 NULL 是默认值,但大多数时候应该使用 NOT NULL,或者使用一个特殊的值,如 0,-1 作为默认值。

为啥建议where中使用默认值代替null,四个原因:

(1)并不是说使用了is null或者 is not null就会不走索引了,这个跟mysql版本以及查询成本都有关;

(2)如果mysql优化器发现,走索引比不走索引成本还要高,就会放弃索引,这些条件 !=,<>,is null,is not null经常被认为让索引失效;

(3)其实是因为一般情况下,查询的成本高,优化器自动放弃索引的;

(4)如果把null值,换成默认值,很多时候让走索引成为可能,同时,表达意思也相对清晰一点;

3、慎用 != 或 <> 操作符。

MySQL 只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些时候的 LIKE。

所以:应尽量避免在 WHERE 子句中使用 != 或 <> 操作符, 会导致全表扫描。

4、慎用 OR 来连接条件

使用or可能会使索引失效,从而全表扫描;

应尽量避免在 WHERE 子句中使用 OR 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,

可以使用 UNION 合并查询:

select id from t where num=10

union all

select id from t where num=20

一个关键的问题是否用到索引。他们的速度只同是否使用索引有关,如果查询需要用到联合索引,用 UNION all 执行的效率更高。多个 OR 的字句没有用到索引,改写成 UNION 的形式再试图与索引匹配。

5、慎用 IN 和 NOT IN

IN 和 NOT IN 要慎用,否则会导致全表扫描。对于连续的数值,能用 BETWEEN 就不要用 IN:select id from t where num between 1 and 3。

6、慎用 左模糊like ‘%…’

模糊查询,程序员最喜欢的就是使用like,like很可能让索引失效。

比如:

select id from t where name like‘%abc%’ select id from t where name like‘%abc’ 而select id from t where name like‘abc%’才用到索引。

所以:

首先尽量避免模糊查询,如果必须使用,不采用全模糊查询,也应尽量采用右模糊查询, 即like ‘…%’,是会使用索引的; 左模糊like ‘%…’无法直接使用索引,但可以利用reverse + function index的形式,变化成 like ‘…%’; 全模糊查询是无法优化的,一定要使用的话建议使用搜索引擎,比如 ElasticSearch。 备注:如果一定要用左模糊like ‘%…’检索, 一般建议 ElasticSearch+Hbase架构

7、WHERE条件使用参数会导致全表扫描。

如下面语句将进行全表扫描:

select id from t where num=@num

因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推 迟到 运行时;

它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。

所以, 可以改为强制查询使用索引:

select id from t with(index(索引名)) where num=@num

8、用 EXISTS 代替 IN 是一个好的选择

很多时候用exists 代替in 是一个好的选择:

select num from a where num in(select num from b) 用下面的语句替换: select num from a where exists(select 1 from b where num=a.num)

9、索引并不是越多越好

索引固然可以提高相应的 SELECT 的效率,但同时也降低了 INSERT 及 UPDATE 的效。

因为 INSERT 或 UPDATE 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。

一个表的索引数最好不要超过 6 个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。

10、尽量使用数字型字段

(1)因为引擎在处理查询和连接时会逐个比较字符串中每一个字符;

(2)而对于数字型而言只需要比较一次就够了;

(3)字符会降低查询和连接的性能,并会增加存储开销;

所以:尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。

11、尽可能的使用 varchar, nvarchar 代替 char, nchar

(1)varchar变长字段按数据内容实际长度存储,存储空间小,可以节省存储空间;

(2)char按声明大小存储,不足补空格;

(3)其次对于查询来说,在一个相对较小的字段内搜索,效率更高;

因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

*14、查询SQL尽量不要使用select ,而是具体字段

最好不要使用返回所有:select * from t ,用具体的字段列表代替 “*”,不要返回用不到的任何字段。

select *的弊端:

(1)增加很多不必要的消耗,比如CPU、IO、内存、网络带宽;

(2)增加了使用覆盖索引的可能性;

(3)增加了回表的可能性;

(4)当表结构发生变化时,前端也需要更改;

(5)查询效率低;

15、将需要查询的结果预先计算好

将需要查询的结果预先计算好放在表中,查询的时候再Select,而不是查询的时候进行计算。

16、IN后出现最频繁的值放在最前面

如果一定用IN,那么:在IN后面值的列表中,将出现最频繁的值放在最前面,出现得最少的放在最后面,减少判断的次数。

17、尽量使用 EXISTS 代替 select count(1) 来判断是否存在记录。

count 函数只有在统计表中所有行数时使用,而且 count(1) 比 count(*) 更有效率。

18、用批量插入或批量更新

当有一批处理的插入或更新时,用批量插入或批量更新,绝不会一条条记录的去更新。

(1)多条提交

INSERT INTO user (id,username) VALUES(1,'xx'); INSERT INTO user (id,username) VALUES(2,'yy');

(2)批量提交

INSERT INTO user (id,username) VALUES(1,'xx'),(2,'yy'); 默认新增SQL有事务控制,导致每条都需要事务开启和事务提交,而批量处理是一次事务开启和提交,效率提升明显,达到一定量级,效果显著,平时看不出来。

19、将不需要的记录在 GROUP BY 之前过滤掉

提高 GROUP BY 语句的效率,可以通过将不需要的记录在 GROUP BY 之前过滤掉。

下面两个查询返回相同结果,但第二个明显就快了许多。

低效:

SELECT JOB, AVG(SAL) FROM EMP GROUP BY JOB HAVING JOB = 'PRESIDENT' OR JOB = 'MANAGER' 高效:

SELECT JOB, AVG(SAL) FROM EMP WHERE JOB = 'PRESIDENT' OR JOB = 'MANAGER' GROUP BY JOB

20、避免死锁

在你的存储过程和触发器中访问同一个表时总是以相同的顺序;事务应经可能地缩短,在一个事务中应尽可能减少涉及到的数据量;永远不要在事务中等待用户输入。

21、索引创建规则:

表的主键、外键必须有索引;

数据量超过 300 的表应该有索引;

经常与其他表进行连接的表,在连接字段上应该建立索引;

经常出现在 WHERE 子句中的字段,特别是大表的字段,应该建立索引;

索引应该建在选择性高的字段上;

索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;

复合索引的建立需要进行仔细分析,尽量考虑用单字段索引代替;

正确选择复合索引中的主列字段,一般是选择性较好的字段;

复合索引的几个字段是否经常同时以 AND 方式出现在 WHERE 子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引;

如果复合索引中包含的字段经常单独出现在 WHERE 子句中,则分解为多个单字段索引;

如果复合索引所包含的字段超过 3 个,那么仔细考虑其必要性,考虑减少复合的字段;

如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引;

频繁进行数据操作的表,不要建立太多的索引; 删除无用的索引,避免对执行计划造成负面影响;

表上建立的每个索引都会增加存储开销,索引对于插入、删除、更新操作也会增加处理上的开销。

另外,过多的复合索引,在有单字段索引的情况下,一般都是没有存在价值的;相反,还会降低数据增加删除时的性能,特别是对频繁更新的表来说,负面影响更大。 尽量不要对数据库中某个含有大量重复的值的字段建立索引。

22、在写 SQL 语句时,应尽量减少空格的使用

查询缓冲并不自动处理空格,因此,在写 SQL 语句时,应尽量减少空格的使用,尤其是在 SQL 首和尾的空格(因为查询缓冲并不自动截取首尾空格)。

23、每张表都设置一个 ID 做为其主键

我们应该为数据库里的每张表都设置一个 ID 做为其主键,而且最好的是一个 INT 型的(推荐使用 UNSIGNED),并设置上自动增加的 AUTO_INCREMENT 标志。

24、使用explain分析你SQL执行计划

(1)type

system:表仅有一行,基本用不到;

const:表最多一行数据配合,主键查询时触发较多;

eq_ref:对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型;

ref:对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取;

range:只检索给定范围的行,使用一个索引来选择行。当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比较关键字列时,可以使用range;

index:该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小;

all:全表扫描;

性能排名:system > const > eq_ref > ref > range > index > all。 实际sql优化中,最后达到ref或range级别。

(2)Extra常用关键字

Using index:只从索引树中获取信息,而不需要回表查询;

Using where:WHERE子句用于限制哪一个行匹配下一个表或发送到客户。除非你专门从表中索取或检查所有行,如果Extra值不为Using where并且表联接类型为ALL或index,查询可能会有一些错误。需要回表查询。

Using temporary:mysql常建一个临时表来容纳结果,典型情况如查询包含可以按不同情况列出列的GROUP BY和ORDER BY子句时;

25、当只要一行数据时使用 LIMIT 1

当你查询表的有些时候,你已经知道结果只会有一条结果,但因为你可能需要去fetch游标,或是你也许会去检查返回的记录数。

在这种情况下,加上 LIMIT 1 可以增加性能。

这样一来,MySQL 数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据。

26、将大的DELETE,UPDATE、INSERT 查询变成多个小查询

能写一个几十行、几百行的SQL语句是不是显得逼格很高?然而,为了达到更好的性能以及更好的数据控制,你可以将他们变成多个小查询。

27、合理分表 尽量控制单表数据量的大小,建议控制在500万以内

500万并不是MySQL数据库的限制,过大会造成修改表结构,备份,恢复都会有很大的问题。

可以用历史数据归档(应用于日志数据),分库分表(应用于业务数据)等手段来控制数据量大小。

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

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

相关文章

网络层--TCP/UDP协议

目录 一、TCP/UDP协议介绍 1、UDP(User Datagram Protocol)--用户数据报协议 1.1 UDP报文格式 1.2 UDP协议的特性 2、TCP(Transmission Control Protocol )--传输控制协议 2.1 TCP报文格式 2.2 TCP协议的特性 2.3 TCP三次握手 2.4 四次挥手 三、TCP和UDP的区别 四、t…

关于“Python”的核心知识点整理大全21

9.3.2 Python 2.7 中的继承 在Python 2.7中&#xff0c;继承语法稍有不同&#xff0c;ElectricCar类的定义类似于下面这样&#xff1a; class Car(object):def __init__(self, make, model, year):--snip-- class ElectricCar(Car):def __init__(self, make, model, year):supe…

xcode 修改 target 中设备朝向崩溃

修改xcode的target中的设备朝向导致崩溃。 从日志上看好像没有什么特别的信息。 之后想了想&#xff0c;感觉这个应该还是跟xcode的配置有关系&#xff0c;不过改动的地方好像也只有plist。 就又翻腾了半天plist中的各种配置项&#xff0c;再把所有的用户权限提示相关的东西之…

运筹学经典问题(三):最大流问题

问题描述 给定一个图网络 G ( V , E ) G(V, E) G(V,E)&#xff0c;网络中连边的权重代表最大容量&#xff0c;在这个图中找出从起点到终点流量最大的路径。 数学建模 集合&#xff1a; I I I&#xff1a;点的集合&#xff1b; E E E&#xff1a;边的集合。 常量&#x…

全光谱的灯对人体有什么伤害?考公护眼台灯推荐

什么是全光谱&#xff1f;全光谱是是一种能够模拟自然光谱的照明设备&#xff0c;通过发出包含所有可见光波长的光线&#xff0c;使人们感受到与自然光类似的照明效果。不同于传统的白炽灯或荧光灯&#xff0c;全光谱灯被认为能够提供更好的视觉质量和更健康的光学经验。现在市…

泊松分布、泊松定理

泊松分布 假设随机变量所有可能的取值为&#xff0c;并且取各个值的概率为&#xff1a; &#xff0c; 其中是常数 那么就称服从参数为的泊松分布&#xff0c;记为。 泊松定理 设是常数&#xff0c;是任意正整数&#xff0c;并且&#xff0c;那么对任意一个非负整数&am…

新一代“垫图”神器,IP-Adapter的完整应用解读

导读 不用训练lora&#xff0c;一张图就能实现风格迁移&#xff0c;还支持多图多特征提取&#xff0c;同时强大的拓展能力还可接入动态prompt矩阵、controlnet等等&#xff0c;这就是IP-Adapter&#xff0c;一种全新的“垫图”方式&#xff0c;让你的AIGC之旅更加高效轻松。 …

14个最经典的git命令,你知道吗?

1 学习14个Git命令&#xff0c;因为你将会在99%的时间里使用它们 必须了解的命令整理 1&#xff0c;git init 初始化一个新的Git仓库。 这将在当前目录中创建一个名为".git"的子目录&#xff0c;Git会将所有仓库的元数据存储在其中。 2&#xff0c;git clone 克…

使用Python绘制二元函数图像详解

概要 在数据科学、数学建模和机器学习中&#xff0c;经常需要可视化二元函数的图像以更好地理解函数的行为。Python提供了丰富的绘图库&#xff0c;如Matplotlib和NumPy&#xff0c;使得绘制二元函数图像变得简便而灵活。本文将介绍如何使用Python创建并美化二元函数图像&…

pandas读取Excel表指定数值 计算总和

题目要求&#xff1a;在一个文件夹里面有424个Excel表格&#xff0c;每个表格中都是统一的&#xff0c;如下图。要求计算所有表格中金额的总和。 上代码&#xff1a; import os import glob import pandas as pd# 指定文件夹路径 folder_path C:\\Users\\Administrator\\Desk…

Salesforce“卷土重来”:对中国CRM市场影响在哪?

于本土CRM而言&#xff0c;Salesforce是一面镜子&#xff0c;也更是催化剂。 长期来看&#xff0c;Salesforce的加入&#xff0c;从某种程度上将会加速中国CRM赛道的合理价值曲线的走向&#xff0c;通过带动外界对于CRM整个赛道的关注和热度&#xff0c;进而加速本土CRM的成长…

Java学习-连接Mysql数据库

1.先在Mysql里面构建一个表格 例子&#xff1a;名字为user1&#xff0c;两列分别为name、score 2.正确导入了MySQL的JDBC驱动程序 2.1 下载驱动包&#xff08;与自己的服务器版本匹配&#xff09; 官网地址&#xff1a;Maven Repository: mysql mysql-connector-java 8.0.29 …

JVM调优:参数(学习笔记)

一、jvm的运行参数 标准参数 -help、-version、-D参数 jvm的标准参数&#xff0c;一般都是很稳定的&#xff0c;在未来的JVM版本中不会改变&#xff0c;可以使用java -help 检索出所有的标准参数。 通过以下命令查看&#xff1a; 命令&#xff1a;java -help 可以看到我们经常…

C与C++编程语言的区别和联系

一、引言 C和C是两种广泛使用的编程语言&#xff0c;它们都在软件开发领域有着广泛的应用。虽然C是从C语言演化而来的&#xff0c;但两者之间存在一些重要的区别和联系。本文将详细介绍这两种编程语言的相同点和不同点&#xff0c;并通过实际例子进行说明。 二、C与C的相同点 …

如何查看Linux中glibc的Version

用ldd --version ldd --version 运行libc.so 你没有看错&#xff0c;libc.so是一个可执行程序。 但前提是你要找到它。因为它并不在PATH所包含的目录下。 ppdell:~$ ldd which cat | grep libclibc.so.6 > /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0e6fb34000)ppdell:~…

GPT-4.5 要来了!谷歌大模型 Gemini 确实给够压力

GPT-4 还没用明白&#xff0c;GPT-4.5 就要发布了。 最近&#xff0c;OpenAI 泄露了 GPT-4.5 的发布页面&#xff0c;除了进一步增强复杂推理和跨模态理解&#xff0c;GPT-4.5 增加了一个更加强大的功能——3D。 3D 功能的进一步支持&#xff0c;也就意味着多模态最后一块版图…

国产Apple Find My「查找」认证芯片-伦茨科技ST17H6x芯片

深圳市伦茨科技有限公司&#xff08;以下简称“伦茨科技”&#xff09;发布ST17H6x Soc平台。成为继Nordic之后全球第二家取得Apple Find My「查找」认证的芯片厂家&#xff0c;该平台提供可通过Apple Find My认证的Apple查找&#xff08;Find My&#xff09;功能集成解决方案。…

基于ssm毕业生跟踪调查反馈系统的设计与实现论文

面向工程教育专业认证的毕业生跟踪调查反馈系统 摘要 随着信息互联网购物的飞速发展&#xff0c;一般企业都去创建属于自己的管理系统。本文介绍了面向工程教育专业认证的毕业生跟踪调查反馈系统的开发全过程。通过分析企业对于面向工程教育专业认证的毕业生跟踪调查反馈系统…

内销开发信的跟进策略?开发信的关键要素?

如何写吸引人的内销开发信&#xff1f;优秀内贸开发信模板推荐&#xff1f; 在当今竞争激烈的市场中&#xff0c;内销开发信扮演着关键的角色&#xff0c;是吸引客户、拓展市场的重要工具。然而&#xff0c;发送一封内销开发信并不是终点&#xff0c;而是一个开始。蜂邮EDM将探…

基于Modis的遥感数据的地表温度的获取解决方案----以京津唐为例

1.背景与技术路线 地表温度(LST)是区域和全球尺度地表物理过程中的一个关键因子,也是研究地表和大气之间物质交换和能量交换的重要参数。许多应用如干旱、高温、林火、地质、水文、植被监测,全球环流和区域气候模型等都需要获得 LST。本方案以北京为例采用星载传感器的红外通道…