MySQL优化-查询优化

MySQL查询优化是指通过调整查询语句、优化表结构、使用索引等方式,提高查询性能的过程。以下是MySQL查询优化的几种方法:

1. 尽量避免使用SELECT*

SELECT *会查询表中的所有列,包括不需要的列,这会消耗大量的计算资源和时间。而且,如果使用了SELECT *,MySQL无法使用索引优化查询,因为MySQL无法确定要查询的列是哪些。这将导致MySQL必须对所有列进行扫描,这将使查询变得非常缓慢。
如果必须使用它,可以考虑以下几个优化策略:

  1. 明确指定要查询的列,而不是使用SELECT *。
  2. 只查询需要的列,避免查询不需要的列。
  3. 使用索引来优化查询,以避免对所有列进行扫描。
  4. 使用缓存来减少查询的开销。

假设有一个名为users的表,包含id、name、age、email等列。如果使用SELECT*查询这个表,会返回所有列的值,即使只需要其中的一部分。而如果只查询id和name列,可以使用:

SELECT id, name FROM users;

这样只会返回需要的列,免了冗余数据的产生,提高了查询效率。

2. 尽量避免使用LIKE ‘%value%’

LIKE ‘%value%’需要对所有数据进行扫描,这会消耗大量的计算资源和时间。如果数据量很大,这些操作可能会变得非常缓慢。

另一方面,如果使用了LIKE ‘%value%’,MySQL无法使用索引优化查询,因为MySQL不知道要匹配的字符串在哪个位置。这将导致MySQL必须对所有数据进行扫描,这将使查询变得非常缓慢。

因此,为了优化MySQL查询性能,我们应该尽量避免使用LIKE ‘%value%’。如果必须使用它,可以考虑以下几个优化策略:

  1. 尽可能缩小查询结果集的大小,以减少扫描的开销。
  2. 尽可能使用索引来优化查询,以避免MySQL无法使用索引优化查询。
  3. 尽可能使用前缀匹配,例如LIKE ‘value%’或LIKE ‘%value’,这样MySQL可以使用索引优化查询。
  4. 尽可能使用全文索引,例如使用MySQL的全文索引功能,以避免LIKE ‘%value%’导致的性能问题。

例如,对于一个文章表,应该使用LIKE 'value%'来提高搜索效率。

SELECT * FROM article WHERE title LIKE 'mysql%';

3. 尽量避免使用NOT IN和NOT EXISTS

一方面,NOT IN和NOT EXISTS需要对所有数据进行扫描,这会消耗大量的计算资源和时间。如果数据量很大,这些操作可能会变得非常缓慢。

另一方面,如果使用了NOT IN和NOT EXISTS,MySQL无法使用索引优化查询,因为MySQL无法确定要查询的数据是否在指定的列表或子查询中。这将导致MySQL必须对所有数据进行扫描,这将使查询变得非常缓慢。

因此,为了优化MySQL查询性能,我们应该尽量避免使用NOT IN和NOT EXISTS。如果必须使用它们,可以考虑以下几个优化策略:

  1. 尽可能使用IN和EXISTS,因为它们可以使用索引优化查询。

  2. 尽可能缩小查询结果集的大小,以减少扫描的开销。

  3. 尽可能使用JOIN操作,因为它可以使用索引优化查询,并且可以在查询结果集上执行其他操作。

  4. 尽可能使用子查询的内部表连接,因为它可以使用索引优化查询,并且可以在查询结果集上执行其他操作。

例如,对于一个订单表和一个产品表,可以使用LEFT JOIN来查询没有订单的产品。

SELECT p.product_id, p.product_name
FROM product p
LEFT JOIN order_detail od ON p.product_id = od.product_id
WHERE od.order_id IS NULL;

4. 尽量避免使用ORDER BY和GROUP BY

ORDER BY和GROUP BY会进行全表扫描,从而增加查询的时间和资源消耗。我们应该尽可能避免使用ORDER BY和GROUP BY。如果必须使用它们,可以考虑以下几个优化策略:

  1. 尽可能缩小查询结果集的大小,以减少排序和分组的开销。
  2. 尽可能使用索引来优化查询,以避免MySQL无法使用索引优化查询。
  3. 尽可能使用覆盖索引,以避免MySQL需要进行回表操作。
  4. 尽可能使用LIMIT来限制查询结果集的大小,以减少排序和分组的开销。
  5. 尽可能使用更快的排序算法,例如使用索引排序而不是文件排序。

假设我们有一个名为students的表,其中包含了学生的ID、姓名、年龄、成绩等信息。我们需要查询年龄大于18岁的学生的姓名和成绩,并按照成绩从高到低进行排序。可以使用以下SQL语句:

SELECT name, score FROM students WHERE age > 18 ORDER BY score DESC;

这个查询语句中,我们使用了WHERE来筛选出年龄大于18岁的学生,然后使用ORDER BY按照成绩从高到低进行排序。这个查询语句在数据量较小的情况下可能没有问题,但是在数据量较大的情况下也会导致查询性能下降,因为MySQL需要对所有符合条件的学生进行排序。

为了避免这个问题,我们可以尝试使用索引来加速查询。可以为agescore两个字段分别创建索引,如下所示:

CREATE INDEX idx_age ON students(age);
CREATE INDEX idx_score ON students(score);

然后修改查询语句,如下所示:

SELECT name, score FROM students USE INDEX (idx_score) WHERE age > 18 ORDER BY score DESC;

这个查询语句中,我们使用了USE INDEX来指定使用idx_score索引来加速查询避免了MySQL对所有符合条件的学生进行排序的问题。

需要注意的是,使用索引来加速查询也并不是适用于所有情况的。在某些情况下,使用索引可能会导致查询性能更差。因此,在进行优化时需要根据具体情况进行权衡和测试。

5. 尽量使用连接(JOIN)来代替子查询(Sub-Queries)

尽量使用连接(JOIN)来代替子查询(Sub-Queries)是一个常见的优化策略。这是因为子查询通常会比连接慢,而且在某些情况下,它们可能会导致性能问题。连接是一种将两个或多个表中的数据合并在一起的方式。而子查询是一种查询语句嵌套在另一个查询语句中的方式。在使用子查询时,MySQL需要先执行子查询,然后再将其结果作为参数传递给外部查询。这种操作会增加查询的复杂度和执行时间。

相比之下,连接通常更快,因为它可以在一次查询中将两个或多个表中的数据合并在一起。这种操作可以减少查询的复杂度和执行时间。

当需要查询多个表中的数据时,尽量使用连接而不是子查询。但是,对于一些特殊的情况,使用子查询可能会更加方便和有效。因此,在实际使用中,需要根据具体情况选择最适合的优化策略。

假设我们有两个表:学生表(students)和成绩表(scores)。学生表包含学生的ID和姓名,成绩表包含学生的ID和成绩。

现在我们需要查询所有成绩大于90分的学生的姓名。我们可以使用连接和子查询两种方式来实现这个查询。

使用子查询:

SELECT name
FROM students
WHERE id IN (SELECT student_id FROM scores WHERE score > 90);

使用连接:

SELECT students.name
FROM students
INNER JOIN scores ON students.id = scores.student_id
WHERE scores.score > 90;

这两种方式都可以得到正确的结果,但是使用连接的查询通常会比使用子查询的查询更快。因为连接可以在一次查询中将两个表中的数据合并在一起,而子查询需要先执行子查询,然后再将其结果作为参数传递给外部查询。所以在这个例子中,使用连接可以减少查询的复杂度和执行时间,从而提高查询的效率。

6. 尽量使用联合(UNION)来代替手动创建的临时表

当我们需要在查询中使用临时表时,MySQL会自动创建一个临时表来存储查询结果。这种方法虽然可以实现我们的查询需求,但是会增加系统的负担,降低查询的效率。

相比之下,使用UNION操作可以将多个查询的结果合并在一起,从而避免了手动创建临时表的过程。这种方法通常比手动创建临时表更高效,因为它可以减少系统的负担并提高查询的速度。

需要注意的是,UNION操作也有一些限制和注意事项。例如,UNION操作会去重,如果需要保留重复的行,则需要使用UNION ALL操作。此外,UNION操作的两个查询必须具有相同的列数和列类型,否则会出现错误。

总之,在MySQL优化中,使用UNION操作来代替手动创建临时表是一种有效的优化方法,可以提高查询的效率并减少系统的负担。

假设我们有两个表,分别是employeescustomers,我们想要将这两个表中的数据合并起来,并统计每个部门的员工和客户数量。可以使用以下SQL语句:

SELECT department, COUNT(*) as count
FROM (SELECT departmentFROM employeesUNION ALLSELECT departmentFROM customers
) t
GROUP BY department;

这个SQL语句中,我们使用了UNION ALL操作将employees表和customers表中的department字段合并起来,然后再使用GROUP BYdepartment字段进行分组统计。这样可以避免手动创建临时表,提高查询性能。

7. 尽量使用索引

使用索引可以加速数据的查找,从而提高查询性能。关于索引以及其优化详见我的另一个博客:MySQL优化-索引优化。下面举一个例子来说明如何使用索引进行优化。

假设我们有一个名为users的表,其中包含了用户的ID、姓名、年龄等信息。我们需要查询年龄为21岁的用户,可以使用以下SQL语句:

SELECT * FROM users WHERE age = 21;

如果users表中的数据量非常大,那么这个查询可能会非常耗时。为了提高查询性能,我们可以在age字段上创建一个索引。可以使用以下SQL语句来创建索引:

CREATE INDEX idx_age ON users(age);

这个SQL语句中,我们使用了CREATE INDEX语句来创建一个名为idx_age的索引,它是基于age字段创建的。

创建索引后,我们再次执行查询语句,可以发现查询速度大大提高了。这是因为MySQL在查询时会使用索引来加速数据的查找,从而提高查询性能。

需要注意的是,索引并不是越多越好。过多的索引会增加数据插入、更新和删除的时间,同时也会占用更多的磁盘空间。因此,在创建索引时需要权衡索引的数量和性能需求,选择合适的索引策略。如果使用的是复合索引,还得考虑最左前缀匹配原则,否则索引起不到理想的效果。

8. 尽量避免在where 子句中的 “=” 左边进行内置函数、算术运算等其他表达式运算

因为MySQL无法将表达式的计算结果与索引中的值进行比较,而是需要对整个表进行扫描,从而导致查询效率低下。

下面举一个例子来说明这个问题。假设我们有一个名为users的表,其中包含了用户的ID、姓名、年龄等信息。我们需要查询年龄为21岁的用户,并且名字的长度为3。可以使用以下SQL语句:

SELECT * FROM users WHERE LENGTH(name) = 3 AND age = 21;

这个查询语句中,我们在WHERE子句中使用了LENGTH函数来计算名字的长度,这就会导致MySQL无法使用索引进行优化。为了避免这个问题,我们可以将LENGTH函数移到SELECT子句中,然后使用别名进行引用,如下所示:

SELECT *, LENGTH(name) AS name_length FROM users WHERE name_length = 3 AND age = 21;

这个查询语句中,我们在SELECT子句中使用了LENGTH函数来计算名字的长度,并使用别名name_length进行引用。然后在WHERE子句中使用了别名name_length来进行筛选,这样就可以避免在WHERE子句中进行函数运算,从而提高查询性能。

需要注意的是,这个优化方法并不是适用于所有情况的。在某些情况下,将函数移到SELECT子句中可能会导致查询性能更差。因此,在进行优化时需要根据具体情况进行权衡和测试。

9. 尽量避免在 where 子句中使用 != 或 <> 操作符

因为这两个操作符会使得查询条件不满足索引最左匹配原则,从而使得查询效率变慢。

举个例子,假设我们有一个名为 students 的表,其中包含了学生的ID、姓名、年龄、成绩等信息。我们需要查询成绩不等于 80 分的学生的姓名和成绩。如果使用 != 或 <> 操作符,查询语句如下:

SELECT name, score FROM students WHERE score != 80;

这个查询语句中,使用了 != 操作符来筛选出成绩不等于 80 分的学生。但是,由于 != 操作符无法使用索引进行优化,MySQL 将不得不扫描整个表来找到符合条件的记录,从而导致查询性能下降。

为了避免这个问题,我们可以使用其他操作符来代替 != 操作符,如下所示:

SELECT name, score FROM students WHERE score < 80 OR score > 80;

这个查询语句中, > 操作符来筛选出成绩不等于 80 分的学生。由于这些操作符可以使用索引进行优化,MySQL 可以快速定位符合条件的记录,从而提高查询性能。

需要注意的是,在某些情况下,使用 != 操作符可能是必要的,但是需要根据具体情况进行权衡和测试。

10. 尽量避免在 where 子句中使用or操作符

因为 OR 操作符会使得查询条件不满足索引最左匹配原则,从而使得查询效率变慢。

举个例子,假设我们有一个表格 students,其中包含了学生的信息,包括姓名和年龄两个字段。如果我们需要查询年龄等于 18 岁或者 20 岁的学生记录,我们可以使用以下 SQL 语句:

SELECT * FROM students WHERE age = 18 OR age = 20;

但是,这个查询语句会导致 MySQL 引擎无法使用 age 字段上的索引来加速查询,因为 OR 操作符会使得查询条件不满足索引最左匹配原则。为了避免这个问题,我们可以使用 IN 操作符来进行查询,例如:

SELECT * FROM students WHERE age IN (18, 20);

这个查询语句可以使用 age 字段上的索引来加速查询,从而提高查询效率。因此,在 MySQL 优化中,尽量避免在 where 子句中使用 OR 操作符是一个很好的实践。总结

查询优化是数据库优化中的一个重要方面,可以提高查询的效率和响应速度,从而提升数据库系统的整体性能。以下是一些查询优化的总结:

  1. 使用索引:索引可以加速查询的速度,因此需要在经常使用的字段上创建索引,避免在 where 子句中使用不等于避免在 where 子句中使用 or 操作符,避免在 where 子句中使用函数,避免在 where 子句中使用模糊查询。

  2. 避免全表扫描:尽量避免使用不带条件的 select 语句,因为这会导致数据库执行全表扫描,而且会消耗大量的系统资源。

  3. 优化 join 操作:join 操作是数据库中经常使用的操作,需要注意 join 的顺序,使用 inner join 代替其他类型的 join,避免在 join 子句中使用 or 操作符。

  4. 避免使用子查询:子查询可以导致性能问题,尽量避免使用子查询,可以使用 join 操作来代替子查询。

综上所述,以上大部分优化查询的方法都是为了避免全表扫描和尽可能利用索引。查询优化是数据库优化中的一个重要方面。为了提高数据库系统的整体性能,需要从多个方面来考虑和优化。

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

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

相关文章

PTA目录树

在ZIP归档文件中&#xff0c;保留着所有压缩文件和目录的相对路径和名称。当使用WinZIP等GUI软件打开ZIP归档文件时&#xff0c;可以从这些信息中重建目录的树状结构。请编写程序实现目录的树状结构的重建工作。 输入格式: 输入首先给出正整数N&#xff08;≤104&#xff09;…

【开源】基于Vue.js的计算机机房作业管理系统的设计和实现

项目编号&#xff1a; S 017 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S017&#xff0c;文末获取源码。} 项目编号&#xff1a;S017&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 登录注册模块2.2 课程管理模块2.3 课…

某app c++层3处魔改md5详解

hello everybody,本期是安卓逆向so层魔改md5教学,干货满满,可以细细品味,重点介绍的是so层魔改md5的处理. 常见的魔改md5有: 1:明文加密前处理 2:改初始化魔数 3:改k表中的值 4:改循环左移的次数 本期遇到的是124.且循环左移的次数是动态的,需要前面的加密结果处理生成 目录…

crmchat安装搭建教程文档 bug问题调试

一、安装PHP插件&#xff1a;fileinfo、redis、swoole4。 二、删除PHP对应版本中的 proc_open禁用函数。 一、设置网站运行目录public&#xff0c; 二、设置PHP版本选择纯静态。 三、可选项如有需求则开启SSL,配置SSL证书&#xff0c;开启强制https域名。 四、添加反向代理。 …

Docker发布简单springboot项目

Docker发布简单springboot项目 在IDEA工具中直接编写Dockerfile文件 FROM java:8COPY *.jar /app.jarCMD ["--server.prot 8080"]EXPOSE 8080ENTRYPOINT ["java", "-jar", "/app.jar"]将项目打包成对应的jar包&#xff0c;将Dockerf…

MySQL 的执行原理(三)

5.4. InnoDB 中的统计数据 我们前边唠叨查询成本的时候经常用到一些统计数据&#xff0c;比如通过 SHOW TABLE STATUS 可以看到关于表的统计数据&#xff0c;通过 SHOW INDEX 可以看到关于索引 的统计数据&#xff0c;那么这些统计数据是怎么来的呢&#xff1f;它们是以什么方…

git下载安装配置及Git在Gitee上拉取和上传代码教程

一、Git下载安装和配置 Git是一个分布式版本控制系统&#xff0c;用于跟踪文件的变化并协作开发。以下是安装和配置Git的简单步骤&#xff1a; 安装Git 下载Git安装程序&#xff1a;Git下载地址。 运行安装程序&#xff0c;按照提示进行安装。 在安装过程中&#xff0c;选择…

Notepad++ 和正则表达式 只保留自己想要的内容

一、需求 如下文本&#xff0c;三段相同结构的数据&#xff0c;想要获取每段结构中‘重复的Ids ’后面的数字 2023-10-26 18:49:49 重复的Ids 26443,26575 要删除的Ids 4174,4199,4200,55502023-10-26 18:49:49 重复的Ids 26436,26443,26575 要删除的Ids 4166,4199,4200,5550…

特殊文件(XML文件)

一&#xff0c;XML文件概括 二&#xff0c;案例 <?xml version"1.0" encoding"UTF-8" ?> <!--注释&#xff1a;以上抬头声明必须写在第一不然报错--> <users><user id"1"><uame>张无忌</uame><性别&g…

bson数据通过BulkOperations批量入库mongo表报重复ID处理

bson数据批量入库mongo表报重复ID处理 一、需求 需要将一批bson格式数据批量入库指定mongo表&#xff0c;并且该表已存在数据&#xff0c;批量入库的数据可能和表中已有数据重复。 二、批量入库时的问题 采用MongoTemplate 原生的BulkOperations批量操作API upsert方法进行…

STM32:OLED屏幕开发

一、OLED原理 所谓的屏幕就是由一个个小灯组成&#xff0c;每个小灯称之为一个像素。只要在屏幕上有选择地点亮一部分小灯&#xff0c;就可以显示我们想要的图案。所谓下分辨率就是屏幕上的小灯数量。常见单片机中常见的屏幕分辨率常见的就是128(列长)*64(行高)。如果每个小灯都…

【云栖 2023】张治国:MaxCompute 架构升级及开放性解读

云布道师 本文根据 2023 云栖大会演讲实录整理而成&#xff0c;演讲信息如下 演讲人&#xff1a;张治国|阿里云智能计算平台研究员、阿里云 MaxCompute 负责人 演讲主题&#xff1a;MaxCompute架构升级及开放性解读 活动&#xff1a;2023云栖大会 MaxCompute 发展经历了三个阶…

发币成功,记录一下~

N年前就听说了这样一种说法——“一个熟练的区块链工程师&#xff0c;10分钟就可以发出一个新的币” 以前仅仅是有这么一个认识&#xff0c;但当时并不特别关注这个领域。 最近系统性学习中&#xff0c;今天尝试发币成功啦&#xff0c;记录一下&#xff5e; 发在 Sepolia Tes…

Minikube Mac安装使用

minikube start | minikube 安装minikube curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 sudo install minikube-darwin-amd64 /usr/local/bin/minikube 1 2 启动本地集群 minikube start --driverdocker # 等待几分钟 让docker 拉…

分布式锁实现对比

1、对比 tairzookeper性能高 低可靠性低 高 2、zookeper实现分布式锁 特点&#xff1a; Zookeeper能保证数据的强一致性&#xff0c;用户任何时候都可以相信集群中每个节点的数据都是相同的。 加锁 客户端在ZooKeeper一个特定的节点下创建临时顺序节点&…

kerberos-MS14-068(kerberos域用户提权)

点击星标&#xff0c;即时接收最新推文 微软官方在2014年11月18日发布了一个紧急补丁&#xff0c;Windows全版本服务器系统受到影响&#xff0c;包括Windows Server 2003&#xff0c;Windows Server 2008&#xff0c;Windows Server 2008 R2&#xff0c;Windows Server 2012和W…

【ROS】RViz2源码分析(三):核心类VisualizerApp

【ROS】郭老二博文之:ROS目录 1、简述 VisualizerApp包含了三个主要的功能: QApplication:程序中主要调用app_->processEvents()来处理刷新界面,处理闪屏VisualizationFrame:窗口类都在此;RosClientAbstractionIface包含rclcpp::Node:代表ROS节点2、VisualizationF…

LeetCode热题100——二分查找

二分查找 1. 搜索插入位置2. 搜素二维矩阵3. 在排序数组中查找第一个和最后一个元素位置 1. 搜索插入位置 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 // 题…

【电路笔记】-星三角变换(Star-Delta Transformation)

星三角变换&#xff08;Star-Delta Transformation&#xff09; 文章目录 星三角变换&#xff08;Star-Delta Transformation&#xff09;1、概述1.1 单相配置1.2 多相配置 2、三相连接2.1 Y配置2.2 Δ配置 3、Y-Δ 和 Δ-Y 变换3.1 Y-Δ变换3.2 Δ-Y变换3.3 应用 4、总结 本文…

蓝桥杯每日一题2023.11.20

题目描述 “蓝桥杯”练习系统 (lanqiao.cn) 题目分析 方法一&#xff1a;暴力枚举&#xff0c;如果说数字不在正确的位置上也就意味着这个数必须要改变&#xff0c;进行改变记录即可 #include<bits/stdc.h> using namespace std; const int N 2e5 10; int n, a[N], …