在大数据量的业务表中执行SQL查询时,全表扫描、复杂关联、无效排序等操作很容易导致查询耗时过长,影响业务正常运转。本文结合实际开发中的高频场景,讲解SQL大数据查询的加速方法。

场景一:单表大数据量查询加速
问题表现
对千万级以上的单表执行条件查询时,没有合适的索引支撑,查询耗时超过10秒甚至更久。
优化方案:合理设计索引
首先分析查询语句的where条件、order by字段、group by字段,针对性创建联合索引,避免冗余索引。可以通过EXPLAIN命令查看执行计划,判断是否使用了索引。
示例表结构如下:
-- 用户订单表,数据量2000万
CREATE TABLE user_order (
id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL,
order_status TINYINT NOT NULL,
create_time DATETIME NOT NULL,
amount DECIMAL(10,2) NOT NULL
);
如果高频查询是查询某个用户最近30天的订单,原始查询语句如下:
SELECT * FROM user_order WHERE user_id = 123 AND create_time >= '2024-01-01' AND create_time < '2024-02-01' ORDER BY create_time DESC;
优化时创建联合索引(user_id, create_time),执行计划会走索引扫描,避免全表扫描:
-- 创建联合索引 CREATE INDEX idx_user_order_user_time ON user_order(user_id, create_time);
场景二:多表关联查询加速
问题表现
多张大表进行join关联时,关联字段没有索引,或者关联顺序不合理,导致查询耗时过长。
优化方案:优化关联逻辑与索引
首先确保关联字段在两张表中都有索引,其次遵循小表驱动大表的原则,调整join的顺序。如果关联时使用了函数处理关联字段,会导致索引失效,需要避免这种写法。
示例:用户表和订单表关联查询用户及其订单信息:
-- 用户表,数据量500万
CREATE TABLE user_info (
id BIGINT PRIMARY KEY,
user_name VARCHAR(50) NOT NULL,
age INT NOT NULL
);
-- 原关联查询,关联字段user_id没有索引,耗时久
SELECT u.user_name, o.order_status, o.amount
FROM user_info u
JOIN user_order o ON u.id = o.user_id
WHERE u.age > 18;
优化步骤:首先给user_order表的user_id字段添加索引,然后调整查询逻辑,先过滤小表数据再关联:
-- 给关联字段添加索引 CREATE INDEX idx_user_order_user_id ON user_order(user_id); -- 优化后的查询,先过滤用户表符合条件的用户,再关联订单表 SELECT u.user_name, o.order_status, o.amount FROM (SELECT id, user_name FROM user_info WHERE age > 18) u JOIN user_order o ON u.id = o.user_id;
场景三:聚合查询加速
问题表现
对大表执行group by、count、sum等聚合操作时,没有合适的索引,或者聚合的字段基数过高,查询效率低下。
优化方案:使用覆盖索引与预聚合
如果聚合查询的字段都在索引中,会使用覆盖索引,不需要回表查询,效率更高。如果聚合查询的频率很高,可以考虑提前预聚合数据,存储到汇总表中。
示例:统计每个用户的订单总金额:
-- 原聚合查询,全表扫描 SELECT user_id, SUM(amount) AS total_amount FROM user_order GROUP BY user_id;
优化时创建包含user_id和amount的联合索引,实现覆盖索引扫描:
-- 创建覆盖索引 CREATE INDEX idx_user_order_user_amount ON user_order(user_id, amount); -- 优化后的查询,走覆盖索引,无需回表 SELECT user_id, SUM(amount) AS total_amount FROM user_order GROUP BY user_id;
通用优化技巧
- 避免使用
SELECT *,只查询需要的字段,减少数据传输和回表开销 - 避免使用
OR连接条件,尽量改成UNION或者IN,避免索引失效 - 定期分析执行计划,通过
EXPLAIN命令查看查询是否走了预期的索引,及时调整优化策略 - 对于大表的删除、更新操作,尽量分批执行,避免长时间锁表影响查询性能
注意:索引并不是越多越好,过多的索引会影响插入、更新、删除操作的性能,需要根据实际查询场景合理设计索引。