SQL 优化笔记:提高查询速度

SQL 优化笔记:提高查询速度

SQL 优化是提升数据库性能的关键环节。以下是一些常见的 SQL 优化策略,包含每种方法的原因和建议,可以帮助提高查询速度和整体性能。

1. 使用索引

1.1 创建索引

原因 :索引可以大大加快数据检索速度,通过创建索引,数据库可以更快地定位到所需数据,而无需扫描整个表。 建议:为查询中经常作为WHERE条件、JOIN条件或ORDER BY的列创建索引。

  • 单列索引:适用于经常作为查询条件的单列。

    复制代码
    sqlCopy CodeCREATE INDEX idx_column_name ON table_name(column_name);
  • 联合索引:适用于多个列一起作为查询条件的情况。

    复制代码
    sqlCopy CodeCREATE INDEX idx_column1_column2 ON table_name(column1, column2);
  • 注意:索引会增加写入操作的开销,避免为每个查询创建过多索引。

1.2 索引选择

原因 :选择性高的列(即唯一值多)能有效提高索引效率。 建议

  • 优先索引选择性高的列,如主键或唯一约束列。
  • 避免过多索引:每增加一个索引都会带来额外的维护开销,特别是对于写操作(插入、更新、删除)。

2. 优化查询语句

2.1 使用合适的查询条件

原因 :不必要的 SELECT * 或函数在 WHERE 子句中会导致全表扫描或失去索引效率。 建议

  • 选择需要的列:只查询实际需要的字段。

    复制代码
    sqlCopy CodeSELECT column1, column2 FROM table_name WHERE condition;
  • 避免在 WHERE 子句中使用不必要的函数:函数调用可能会导致索引失效。

    复制代码
    sqlCopy Code-- 不推荐
    SELECT * FROM table_name WHERE YEAR(date_column) = 2023;
    
    -- 推荐
    SELECT * FROM table_name WHERE date_column BETWEEN '2023-01-01' AND '2023-12-31';

2.2 使用 JOIN 而非子查询

原因JOIN 通常比子查询性能更优,尤其是在处理大数据集时。 建议

  • 使用 JOIN 替代子查询:在可能的情况下,尽量使用连接查询而非嵌套查询。

    sql 复制代码
    sqlCopy Code-- 子查询
    SELECT * FROM orders WHERE customer_id IN (SELECT customer_id FROM customers WHERE status = 'active');
    
    -- JOIN 查询
    SELECT orders.* FROM orders JOIN customers ON orders.customer_id = customers.customer_id WHERE customers.status = 'active';

2.3 小表驱动大表

原因 :小表驱动大表,也就是说用小表的数据集驱动大表的数据集。

假如有order和user两张表,其中order表有10000条数据,而user表有100条数据。

这时如果想查一下,所有有效的用户下过的订单列表。

可以使用in关键字实现:

sql 复制代码
select * from order
where user_id in (select id from user where status=1)

也可以使用exists关键字实现:

sql 复制代码
select * from order
where exists (select 1 from user where order.user_id = user.id and status=1)

前面提到的这种业务场景,使用in关键字去实现业务需求,更加合适。

为什么呢?

因为如果sql语句中包含了in关键字,则它会优先执行in里面的子查询语句,然后再执行in外面的语句。如果in里面的数据量很少,作为条件查询速度更快。

而如果sql语句中包含了exists关键字,它优先执行exists左边的语句(即主查询语句)。然后把它作为条件,去跟右边的语句匹配。如果匹配上,则可以查询出数据。如果匹配不上,数据就被过滤掉了。

这个需求中,order表有10000条数据,而user表有100条数据。order表是大表,user表是小表。如果order表在左边,则用in关键字性能更好。

总结一下:
in 适用于左边大表,右边小表。
exists 适用于左边小表,右边大表。
不管是用in,还是exists关键字,其核心思想都是用小表驱动大表。

2.4 优化分页查询

**原因:**当使用LIMIT和OFFSET进行分页时,随着页码的增加,查询性能会逐渐下降,因为数据库需要扫描越来越多的行来找到所需的起始点。

**建议:**使用基于索引的查询来优化分页,特别是当表很大时。例如,可以记录上一页最后一条记录的某个唯一标识符(如ID),并使用它作为下一页查询的起点。

例子:

优化前(随着页码增加性能下降)

复制代码
SELECT * FROM user LIMIT 10 OFFSET 100;

优化后(使用上一页的最后一条记录的ID)

复制代码
SELECT * FROM user WHERE id > LAST_SEEN_ID ORDER BY id LIMIT 10
相关推荐
whcyhhh38 分钟前
头歌实践教学平台:大数据存储2023(六)
大数据·数据库·python
Elastic 中国社区官方博客2 小时前
让大模型思考,让小模型执行:在 Elastic Workflows 中拆分 LLM 成本
大数据·运维·数据库·人工智能·elasticsearch·ai
Faith_xzc2 小时前
一条 SQL 顶一条 Flink 链路?Doris Streaming Job 持续导入全景解析
大数据·数据库·sql·flink
爱学习的小白柏2 小时前
【AI问数技术】多Agent协同架构:查询规划/SQL生成/洞察分析/报告生成
java·网络·人工智能·windows·sql·架构·llama
摆烂z3 小时前
简单理解StarRocks
sql
IZero073 小时前
Elasticsearch 学习笔记筑基-文档操作篇
笔记·学习·elasticsearch
公爵爱学习3 小时前
安装Ubuntu20.04遇到的问题 简要简述笔记
笔记
这个DBA有点耶5 小时前
多模数据库深度解读:从“多库拼装”到“一库多能”的架构演进
数据库·mysql·dba
程序员夏洛5 小时前
MySQL 默认的事务隔离级别是什么?为什么选择这个级别?
数据库·mysql
Wang's Blog5 小时前
PostgreSQL笔记28: PostgreSQL ACID 特性与实现机制深度解析
大数据·笔记·postgresql