MySQL · 性能优化 · 提高查询效率的实用指南(上)

news2024/11/12 21:37:39

前言

在过去的几年里,MySQL作为一款开源数据库,因其稳定性和性能得到了广泛的应用。始终保持着强劲的增长趋势,越来越多的企业和开发者将其作为首选数据库,甚至有部分企业从Oracle迁移至MySQL。然而,随着使用的普及,MySQL在实际应用中也暴露出了一些常见问题,尤其是当SQL语句不够优化时,可能会导致响应时间慢、CPU使用率高等性能瓶颈问题。

请在此添加图片描述

今天我总结了常见的SQL错误用法,供大家参考:

LIMIT 语句

错误用法: 在应用程序中,分页查询是非常常见的操作场景。然而,LIMIT语句在数据量较大的情况下容易出现性能问题。

SELECT
	*
FROM
	operation
WHERE
	type = 'SQLStats'
AND NAME = 'SlowLog'
ORDER BY
	create_time
LIMIT 1000, 10;

LIMIT参数较小时,例如LIMIT 1000, 10,查询性能尚可,但当参数变为LIMIT 1000000,10时,即使程序员仅需提取10条记录,查询时间依然可能显著增加。原因在于数据库必须从头开始扫描并计算每一行,直到达到所需的记录位置。

优化方案: 为了避免这种性能问题,可以通过重新设计SQL语句,将上一页的最大值作为查询条件。

SELECT
	*
FROM
	operation
WHERE
	type = 'SQLStats'
AND NAME = 'SlowLog'
AND create_time > '2017-03-16 14:00:00'
ORDER BY
	create_time
LIMIT 10;

这种方式确保了查询时间基本固定,不会随着数据量的增长而变化。

原理解析: MySQL在执行LIMIT查询时,必须遍历满足条件的所有记录,直到到达指定的偏移量。因此,随着LIMIT偏移量的增加,查询的时间复杂度线性增加。通过将上一页的最大值作为查询条件,可以避免数据库扫描大量无关记录,从而大幅提高查询效率。


隐式转换

错误用法: SQL语句中字段类型与查询变量类型不匹配是另一个常见错误。

EXPLAIN EXTENDED SELECT
	*
FROM
	my_balance b
WHERE
	b.bpn = 14000000123
AND b.isverified IS NULL;

在上述语句中,bpn字段定义为varchar(20),而查询条件中的14000000123是一个整数。MySQL会自动将字符串转换为数字再进行比较,这会导致索引失效,进而影响查询性能。

优化方案: 为避免隐式转换,应确保查询变量与字段类型一致。例如,可以将查询条件中的整数转换为字符串形式:

SELECT
	*
FROM
	my_balance b
WHERE
	b.bpn = '14000000123'
AND b.isverified IS NULL;

原理解析: 当MySQL遇到类型不匹配的情况时,会尝试进行隐式转换,以确保语句能够执行。然而,这种转换通常会导致索引失效,因为索引的原始数据类型与转换后的数据类型不匹配。因此,查询效率会大幅下降。通过确保查询条件与字段类型一致,可以避免不必要的转换操作,从而提升查询效率。


关联更新、删除

错误用法: 虽然MySQL 5.6引入了物化特性来优化查询性能,但对于更新或删除操作,仍需手工重写为JOIN,以提高执行效率。例如,以下UPDATE语句的执行方式为循环嵌套子查询(DEPENDENT SUBQUERY):

UPDATE operation o
SET STATUS = 'applying'
WHERE
	o.id IN (
		SELECT
			id
		FROM
			(
				SELECT
					o.id,
					o. STATUS
				FROM
					operation o
				WHERE
					o. GROUP = 123
				AND o. STATUS NOT IN ('done')
				ORDER BY
					o.parent,
					o.id
				LIMIT 1
			) t
	);

优化方案: 通过将子查询改写为JOIN,可以显著提高更新语句的执行速度:

UPDATE operation o
JOIN (
	SELECT
		o.id,
		o. STATUS
	FROM
		operation o
	WHERE
		o. GROUP = 123
	AND o. STATUS NOT IN ('done')
	ORDER BY
		o.parent,
		o.id
	LIMIT 1
) t ON o.id = t.id
SET STATUS = 'applying';

原理解析: MySQL在处理嵌套子查询时,需要为每一行执行子查询,这通常会导致性能问题。而JOIN操作通过在一张表中查找匹配的行,避免了多次子查询的执行,从而显著提升性能。


混合排序

错误用法: MySQL通常无法利用索引进行混合排序,但在某些场景下可以通过特殊的重写方式提高性能。

以下查询语句执行计划显示为全表扫描:

SELECT
	*
FROM
	my_order o
INNER JOIN my_appraise a ON a.orderid = o.id
ORDER BY
	a.is_reply ASC,
	a.appraise_time DESC
LIMIT 0, 20;

优化方案: 可以将查询拆分为两个部分并合并结果,从而提高查询效率:

SELECT
	*
FROM
	(
		(
			SELECT
				*
			FROM
				my_order o
			INNER JOIN my_appraise a ON a.orderid = o.id
			WHERE
				is_reply = 0
			ORDER BY
				appraise_time DESC
			LIMIT 0,
			20
		)
		UNION ALL
			(
				SELECT
					*
				FROM
					my_order o
				INNER JOIN my_appraise a ON a.orderid = o.id
				WHERE
					is_reply = 1
				ORDER BY
					appraise_time DESC
				LIMIT 0,
				20
			)
	) t
ORDER BY
	is_reply ASC,
	appraise_time DESC
LIMIT 20;

原理解析: MySQL在混合排序的情况下,通常需要对整个数据集进行排序,这会导致较高的计算成本。通过将查询拆分为多个部分,再合并结果,可以减少MySQL在排序过程中的负担,进而提高查询速度。


EXISTS语句

错误用法: MySQL在处理EXISTS子句时,仍然采用嵌套子查询的执行方式,这会导致性能问题。

SELECT
	*
FROM
	my_neighbor n
LEFT JOIN my_neighbor_apply sra ON n.id = sra.neighbor_id
AND sra.user_id = 'xxx'
WHERE
	n.topic_status < 4
AND EXISTS (
	SELECT
		1
	FROM
		message_info m
	WHERE
		n.id = m.neighbor_id
	AND m.inuser = 'xxx'
)
AND n.topic_type <> 5;

优化方案: 可以通过将EXISTS子查询改写为JOIN来提高查询效率:

SELECT
	*
FROM
	my_neighbor n
INNER JOIN message_info m ON n.id = m.neighbor_id
AND m.inuser = 'xxx'
LEFT JOIN my_neighbor_apply sra ON n.id = sra.neighbor_id
AND sra.user_id = 'xxx'
WHERE
	n.topic_status < 4
AND n.topic_type <> 5;

原理解析: MySQL在执行EXISTS子查询时,会为主查询的每一行执行一次子查询,导致性能问题。通过将EXISTS改写为JOIN,可以避免不必要的重复查询,从而显著提高执行效率。

总结

数据库编译器负责生成执行计划,这一计划将决定SQL语句的实际执行方式。然而,编译器仅仅是尽力而为,因为所有数据库的编译器都并非完美无缺。许多性能问题在其他数据库系统中也同样存在。唯有深入了解数据库编译器的特性,我们才能规避其不足之处,从而编写出高性能的SQL语句。

因此,在设计数据模型和编写SQL语句时,程序员需要将算法的思想或意识融入其中。

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

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

相关文章

体型控制器:S6K1,相关磷酸化抗体介绍

前 言 S6K1是一种丝氨酸/苏氨酸蛋白激酶&#xff0c;因能介导核糖体蛋白S6磷酸化而得名。众所周知&#xff0c;胞内蛋白磷酸化在多种生理及病理过程中发挥重要作用&#xff0c;并与癌症的发生发展关系密切。除此之外&#xff0c;S6K1还有控制体型的功能&#xff0c;下文我们将…

activiti学习第一步

此处无简介&#xff08;有需要可以官网查询&#xff09;直接上使用 引入pom <activiti.version>7.1.0.M2</activiti.version><dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter</artifa…

学生用的蓝牙耳机推荐有哪些?实测四款实力出众机型!

在当今数字化学习环境中&#xff0c;学生对蓝牙耳机的需求日益增长&#xff0c;无论是在线课程的学习、图书馆的集中阅读还是日常通勤中的音频资料复习&#xff0c;一款性能优异、舒适度高且价格合理的蓝牙耳机对学生来说至关重要&#xff0c;面对市场上琳琅满目的产品选择&…

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取相机当前数据吞吐量(Python)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK里函数来获取相机当前数据吞吐量&#xff08;Python&#xff09; Baumer工业相机Baumer工业相机的数据吞吐量的技术背景CameraExplorer如何查看相机吞吐量信息在NEOAPI SDK里通过函数获取相机接口吞吐量 Baumer工业相机通过NEOAPI…

【方法】如何禁止PDF转换成其他格式文件?

在工作中&#xff0c;PDF文件因其易于阅读和不易修改的特性&#xff0c;成为了广泛使用的文件格式。然而&#xff0c;出于安全性或版权保护的考虑&#xff0c;有时候我们不希望他人将PDF文件转换为其他格式。下面一起来看看禁止PDF转换格式的方法&#xff01; 我们只需要通过P…

java 上传代码到线上流程

1. idea 的 maven 插件环境选择 test 或者 prod test 对应物理机&#xff0c;prod对应线上生产环境 2. 选择完成要重新刷新 maven 3. 第一部 首先 clean 第二部进行 package jar 包路径一般在 WeiCar-Server\ruoyi-admin\target 下 去宝塔更新 Jar 包重启项目即可

C++入门 二(函数重载,引用,超详细!!!)

文章目录 函数重载函数重载的概念 引用引用的概念引用特性 函数重载 函数重载的概念 函数重载:是函数的一种特殊情况&#xff0c;C允许在同一作用域中声明几个功能类似的同名函数&#xff0c;这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同&#xff0c;常用来处理…

uni-app和Node.js使用uni-push2.0实现通知栏消息推送功能

前言 uniapp 提供了 unipush 统一推送服务,但是每次要推送消息的时候都要登陆 Dcloud 开发者后台&#xff0c;有点不方便&#xff0c;运营需要在我们的后台系统就可以完成操作。 效果演示 消息下发流程 名词解释 名词解释通知消息指定通知标题和内容后&#xff0c;由个推 SD…

【文档资料】《你缺失的那门计算机课》

# 站长的话 站长认为此书写的非常好&#xff0c;能够很好的GET到当下普通人所遇到的难点&#xff0c;正如此书的序章所写&#xff1a;“据我们观察&#xff0c;许多同学对「电脑」并不熟悉&#xff0c;甚至可以说是陌生&#xff1a;他们可能在网上被下载到各种「P2P 高速下载器…

【大模型结构】输出参数配置

文章目录 大模型生成策略Top_kTop_pTemperature联合使用的顺序参考资料 大家在体验大语言模型或者多模态大模型的开源应用时&#xff0c;经常会看到类似下面这个页面&#xff0c;用来控制大模型输出的一些参数设置&#xff1a; 或者在代码中也经常需要设置以下几个参数&#xf…

git-describe获取不到新创建的标签

一、问题描述 1、新建的分支 2、git-describe 失败 二、查询资料 &#xff08;1&#xff09;git-describe - 根据可用的ref给对象一个人类可读的名称 &#xff08;2&#xff09;该命令查找可从提交访问的最新标记。如果标记指向提交&#xff0c;则仅显示标记。否则&#xf…

权威认证 | HelpLook荣获ISO 27001认证,信息安全能力获国际认可

“信息&#xff0c;如同其他核心业务资产&#xff0c;同样具有极高的价值。” 有很多用户关心&#xff0c;在HelpLook上传的数据安全有保障吗&#xff1f;其实&#xff0c;HelpLook早已通过了国际权威的ISO 27001信息安全管理体系认证。这一认证不仅标志着HelpLook的信息安全管…

服务业如何运用控制图来监控服务质量?

控制图&#xff0c;最初起源于制造业&#xff0c;用于监控生产过程中的质量波动&#xff0c;确保产品符合预定标准。然而&#xff0c;其原理同样适用于服务业&#xff0c;成为衡量和监控服务质量的得力助手。通过收集关键服务指标的数据&#xff08;如客户满意度、服务响应时间…

不信这个书单治不了你的大模型焦虑症!学习大模型最值得推荐的几本书

前言 要说现在最热门的技术&#xff0c;可谓非大模型莫属&#xff01; 不少小伙伴都想要学习大模型技术&#xff0c;转战AI领域&#xff0c;以适应未来的大趋势&#xff0c;寻求更有前景的发展~~ 然而&#xff0c;在学习大模型技术这条道路上&#xff0c;却不知道如何进行系…

Vue3 TS 验证子组件中的表单,多级表单验证

Vue3 TS 验证子组件中的表单&#xff0c;多级表单验证 1. 使用情形2. 子组件script中定义并expose3. 父组件使用 1. 使用情形 在某些交互场景下&#xff0c;我们同一个页面会嵌套多个表单&#xff0c;例如表单2为表单1的子组件里的表单&#xff0c;但是我们需要在提交场景下同…

centos 7 升级Docker 与Docker-Compose 到最新版本

一 升级docker 可参考docker官方升级 1, 查看docker 信息 docker info 2,查看docker 版本 docker --version 3 升级前 可停止docker : sudo systemctl stop docker 4 查看已安装的docker 并卸载 [rootlocalhost docker]# yum list installed | grep docker docker.x86…

Java学习中,强制类型转换时,没有检查兼容性,引发 ClassCastException怎么办?

Java是一门强类型语言&#xff0c;这意味着在编译时&#xff0c;变量的数据类型已经确定。然而&#xff0c;在实际开发过程中&#xff0c;可能会遇到将对象转换为其他类型的需求&#xff0c;这时就会涉及到类型转换问题。Java提供了自动类型转换和强制类型转换两种方式来处理不…

中秋节好物抢先看!中秋佳节有什么好用又实惠的好物推荐!

中秋佳节即将悄然而至&#xff0c;你是否已经开始为家中的温馨氛围挑选那些寓意团圆与美好的中秋好物&#xff1f;一年一度的中秋佳节&#xff0c;正是我们精心筹备&#xff0c;以物寄情&#xff0c;共享天伦之乐的美好时刻。错过了此刻的精选与筹备&#xff0c;便需再等一年&a…

《Python编程:从入门到实践》外星人入侵

一、规划 在游戏《外星人入侵》中&#xff0c;玩家控制着一艘最初出现在屏幕底部中央的飞船。玩家可以使用箭头键左右移动飞船&#xff0c;还可使用空格键进行射击。游戏开始时&#xff0c;一群外星人出现在天空中&#xff0c;他们在屏 幕中向下移动。玩家的任务是射杀这些外星…

进程查看和计划任务

进程查看 用top查看 其中stopped为前台任务在后台暂停 jobs&#xff1a;查看系统有多少暂停任务 fg 进程序号&#xff1a;进入暂停任务 M&#xff1a;按内存占比排序 P&#xff1a;按cpu占比排序 写一个死循环脚本并杀死 #!/bin/bash NUM0 while(($NUM<3)) doecho &qu…