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

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

maynowei10个月前 (09-11)技术知识127

注:本期视频需要一点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全解> 的相关资料哦~

相关文章

ExpandListView 的一种巧妙写法(三十的另一种写法)

ExpandListView大家估计也用的不少了,一般有需要展开的需求的时候,大家不约而同的都想到了它然后以前自己留过记录的一般都会找找以前自己的代码,没有记录习惯的就会百度、谷歌,这里吐槽一下,好几...

掌握C语言多线程:高效并发编程指南

一、多线程基础概念介绍多线程编程是现代软件开发中提高程序性能和响应性的重要技术。在C语言中,pthread(POSIX Threads)库是实现多线程编程的标准工具。本节将通俗易懂地介绍多线程的核心概...

Linux系统编程:条件变量为什么要用锁

条件变量可以解决线程同步和共享资源访问的问题,条件变量是对互斥锁的补充,它允许一个线程阻塞并等待另一个线程发送的信号,当收到信号时,阻塞的线程被唤醒并试图锁定与之相关的互斥锁。具体定义如下:等待:in...

c++ 继承简介(c++继承的概念)

24.1 — 继承简介2024 年 6 月 5 日在上一章中,我们讨论了对象组合,即从更简单的类和类型构建复杂类。对象组合非常适合构建与其部分具有“has-a”关系的新对象。但是,对象组合只是 C++...

电视剧智能换脸怎么做到的?这个在线网站可以帮你!

时代已经改变,怎么能不享受智能化带来的便利呢?今天就给大家带来一个智能又好玩的网站。在「AI智能换脸」这个网站上,你只需要动动手指,就可以轻松换脸成为大片中的角色,契合度高达 80%。AI智能换脸网站...

PostgreSQL是不是你的下一个JSON数据库?

根据Betteridge定律(任何头条的设问句可以用一个词来回答:不是),除非你的JSON数据很少修改,并且查询很多。最新版的PostgreSQL添加更多对JSON的支持,我们曾经问过PostgreS...