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

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

maynowei6个月前 (09-11)技术知识79

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

相关文章

如何快速将axure生成的原型放到手机上演示

人人都是产品经理旗下【起点学院】推出产品经理“365天”成长计划,BAT大牛带你学产品! 之前Axure官方有一个原型在线分享演示的平台,用户可以直接生成原型到Axure官方平台,方便用户提供演示:h...

出售闲置原型素材来赚钱,上传作品,即可收上万元收入

出售闲置原型素材来赚钱。产品经理每年设计出大量的原型作品和组件、元件库、交互原型模板等作品,如果项目结束,你的原型就失去了作用,而有需求的人却找不到这样的作品。现在我们发现这样一家元件库、原型模板、素...

Objective-C的本质(objective-c的特点)

我们平时编写的Objective-C代码,底层实现其实都是C\C++代码,所以Objective-C的面向对象都是基于C\C++的数据结构实现的OC对象的本质Objective-C的对象、类主要是基于...

大势所趋:Swift受欢迎度即将赶超Objective C

Swift是Apple在WWDC2014所发布的一门编程语言,用来撰写OS X和iOS应用程序。不到两年时间,在iOS开发者中Swift语言便凭借着简洁的语法和优秀的特性打动了开发者,之前用于iOS和...

微软明年要停止SQL Server 2005的技术支持了

站长之家(Chinaz.com)12月28日消息据外媒消息称,微软将于明年停止为SQL Server 2005提供技术支持,即不再为其提供新的安全补丁、新功能、应用升级等服务。且表示在停止技术支持后,...

Linux系统编程—互斥量mutex(linux 互斥量)

##互斥量mutex前文提到,系统中如果存在资源共享,线程间存在竞争,并且没有合理的同步机制的话,会出现数据混乱的现象。为了实现同步机制,Linux中提供了多种方式,其中一种方式为互斥锁mutex(也...