当前位置:首页 > 技术文章 > 正文内容

SQL全知全解之性能优化~性能优化十个小技巧!

zonemu7小时前技术文章3

注:本期视频需要一点SQL语法基础,如果对基础有疑问的可以参考上期文章<MySQL基础全知全解>~

本期内容乏味且枯燥,如有需要或是想要了解学习请耐心观看

<( ̄︶ ̄)↗[GO!GO!GO!]

全篇文字2000+


在数据库管理和应用开发中,SQL 查询的性能优化至关重要。高效的 SQL 查询不仅可以提高应用的响应速度,还能降低服务器负载,提升用户体验。接下来,我将分享 SQL 优化的实用技巧,并结合具体代码示例,帮助你构建高效、稳定的数据库应用( ̄︶ ̄)↗ 


1、查询设计优化

(一)选择合适的查询字段

只检索需要的列,避免使用SELECT *。例如,如果只需要用户的姓名和年龄,应写成:

SELECT name, age FROM users;

而不是SELECT * FROM users。这样可以减少数据传输量,提高查询性能。


(二)使用索引

为经常用于查询条件(如WHERE子句)、连接条件(JOIN子句)的列创建索引。假设存在orders表,经常根据订单日期order_date进行查询,可通过以下语句创建索引:

CREATE INDEX idx_order_date ON orders (order_date);

注意:索引不是越多越好,过多的索引会增加插入、更新和删除操作的成本。


(三)避免使用子查询(在适当的时候)

有时候子查询可以用连接(JOIN)来代替。

例如,查询每个部门的员工人数,使用连接的方式:

SELECT d.department_name, COUNT(e.employee_id)
FROM departments d
JOIN employees e ON d.department_id = e.department_id
GROUP BY d.department_name;

比使用子查询更高效一丝丝( ̄︶ ̄)↗ 


(四)优化子查询(当必须使用时)

如果子查询不可避免,确保子查询的条件尽可能简单。比如,从orders表中查询金额大于平均订单金额的订单,优化后的子查询代码:

SELECT * FROM orders
WHERE order_amount > (
    SELECT AVG(order_amount)
    FROM orders
);

避免在子查询中进行复杂计算,如:

-- 不推荐,子查询包含复杂计算
SELECT *
FROM orders
WHERE order_amount > (
    SELECT SUM(order_amount)  COUNT(*)
    FROM orders
    WHERE order_date >= '2024-01-01' AND order_date <= '2024-12-31'
);


(五)使用临时表(谨慎使用)

对于复杂的查询,有时可以将中间结果存储在临时表中。例如,先查询出每个月的订单总金额存入临时表,再基于临时表查询总金额最高的月份:

-- 创建临时表存储每个月订单总金额
CREATE TEMPORARY TABLE monthly_order_total AS
SELECT 
    YEAR(order_date) AS order_year,
    MONTH(order_date) AS order_month,
    SUM(order_amount) AS total_amount
FROM 
    orders
GROUP BY 
    YEAR(order_date), MONTH(order_date);

-- 从临时表查询总金额最高的月份
SELECT 
    order_year,
    order_month,
    total_amount
FROM 
    monthly_order_total
WHERE 
    total_amount = (SELECT MAX(total_amount) FROM monthly_order_total);

创建和维护临时表会占用额外资源。


(六)避免使用OR条件(在可能的情况下)

OR条件可能会使查询优化器无法有效地使用索引。如果可能,可以将OR条件转换为UNION操作。例如,查询年龄为 20 岁或者姓名为 “张三” 的用户:

-- 不太好的写法
SELECT * FROM users WHERE age = 20 OR name = '张三';

-- 较好的写法
SELECT * FROM users WHERE age = 20
UNION
SELECT * FROM users WHERE name = '张三';


(七)使用EXISTS代替IN(在适当的时候)

当子查询结果集较大时,EXISTS通常比IN更高效。例如,查询有订单的用户:

EXISTS一旦找到匹配的记录就会停止查询子查询。

-- 使用EXISTS
SELECT * FROM users u
WHERE EXISTS (SELECT 1 FROM orders o WHERE u.user_id = o.user_id);

-- 使用IN
SELECT * FROM users u
WHERE u.user_id IN (SELECT user_id FROM orders);

<EXISTS>注解:EXISTS子查询只关注子查询是否能返回结果行,而不关心返回的具体数据内容 。使用SELECT 1,这里的1可以替换为任何常量(如SELECT 0SELECT 'x'等),数据库不会实际去获取和处理这个值,只是判断子查询是否有数据返回。如果子查询(SELECT 1 FROM orders o WHERE u.user_id = o.user_id)能找到满足条件的记录,即存在与users表中某用户关联的订单记录,那么EXISTS条件就为TRUE,主查询会将对应的用户记录选取出来。


(八)优化GROUP BY和HAVING子句

确保GROUP BY子句中的列是索引的一部分,这样可以提高分组操作的性能。对于HAVING子句,尽量将过滤条件放在WHERE子句中(如果可能)。比如,查询平均订单金额大于 100 且订单数量大于 5 的用户:

-- 较好的写法,先在WHERE过滤数据,再分组和HAVING过滤
SELECT user_id, AVG(order_amount) AS avg_amount, COUNT(*) AS order_count
FROM orders
WHERE order_amount > 50 -- 提前过滤
GROUP BY user_id
HAVING AVG(order_amount) > 100 AND COUNT(*) > 5;

-- 不好的写法,未在WHERE过滤
SELECT user_id, AVG(order_amount) AS avg_amount, COUNT(*) AS order_count
FROM orders
GROUP BY user_id
HAVING AVG(order_amount) > 100 AND COUNT(*) > 5 AND order_amount > 50;


(九)优化DISTINCT操作

如果DISTINCT操作涉及的列有索引,可以提高查询效率。并且尽量减少使用DISTINCT。例如,查询唯一的部门名称:

-- 假设department_name列有索引
SELECT DISTINCT department_name FROM departments;


(十)优化ORDER BY子句

对 <ORDER BY> 子句中的列创建索引,可以加快排序速度。如果可能,将ORDER BY和LIMIT结合使用,减少排序的数据量。例如,查询工资最高的前 10 名员工:

-- 假设salary列有索引
SELECT * FROM employees ORDER BY salary DESC LIMIT 10;



以上就是本期分享的SQL语法上的十个优化小技巧啦,如果本期文章对你有所帮助,请点赞收藏一下吧!同时SQL优化不仅仅在于语法上,合理的表结构设计数据库配置等也是至关重要的。


结尾彩蛋:本期特别枯燥,能看到末尾说明你很希望提升自己的SQL相关能力,这里准备了一份小“礼物”,私信“SQL学习”则可获得一份关于 <高性能SQL全解> 的相关资料哦~

相关文章

vue3-内置组件-Teleport(vue内置指令有哪些)

Teleport<Teleport> 是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。基本用法有时我们可能会遇到这样的场景:一个组件模板的一部...

Jenkins 学习笔记(jenkins要学多久)

本学习笔记参考《Jenkins 2.x实践指南》。1. Jenkins 简介#Jenkins 是一款自动化的任务执行工具。通常用于持续集成/持续交付领域。可以通过界面或Jenkinsfile告诉Jen...

基于Docker构建安装Git/GitLab,以及制作springboot工程镜像

今天给大家分享的是《领先的开源自动化服务器Jenkins的应用实战》之基于Docker安装构建Git/GitLab版本控制与代码云存储的场所;使用Git管理项目,springboot工程制作镜像知识体...

HTML5设计与制作哪家强?全省50多所高职院校齐聚中山比拼

3月22日下午,2018-2019年广东省职业院校学生专业技能大赛“HTML5交互融媒体内容设计与制作”赛项在中山火炬职业技术学院开幕。全省51所高职院校的52支参赛队伍参加此次大赛。参赛师生将于3月...

web前端是什么,在哪些地方有应用,html和html5区别都在这里了

web前端是什么,在哪些地方有应用简介web前端开发技术什么是html、html5什么是css、css3什么是js,javascriptweb前端的应用大家好,我是ots_luo,很多小伙伴不知道we...

简析html5、html的13条区别(html5和html的突出优点)

html5的流行近一两年,在国内主要是移动端和html5游戏的发展,国外也是最近纷纷使用html5,如谷歌,全面的停止flash的广告的投放量,用html5取代之,那么html5较html的区别在哪里...