文章目录
- SQL优化最佳实践分析与总结
- 1.2.1. 避免使用 `SELECT \*`
- 1.2.2. 小表驱动大表
- 1.2.3. 用连接查询代替子查询
- 1.2.4. 提升 `GROUP BY` 的效率
- 1.2.5. 批量操作
- 1.2.6. 使用 `LIMIT` 优化查询
- 总结
SQL优化最佳实践分析与总结
SQL查询性能的优化是数据库设计与使用中的核心问题之一,通过以下六大实践,我们可以显著提升查询效率,降低资源消耗:
1.2.1. 避免使用 SELECT \*
原因:
- 查询解析成本增加:
SELECT *
会将字段解析为所有列,这一过程增加了解析器的负担。 - 覆盖索引失效:
SELECT *
通常无法利用覆盖索引,会导致大量回表查询,效率低下。 - 网络传输负担:无用字段的传输,特别是大字段 (如
TEXT
) 会浪费带宽。
优化建议:
- 明确列出所需字段,确保查询列与索引列匹配。
- 使用工具(如
SHOW WARNINGS
)检查字段映射与优化建议。
1.2.2. 小表驱动大表
原理:
在 JOIN 操作中,优化器优先使用驱动表的索引匹配被驱动表的数据。小表作为驱动表能减少扫描次数,降低磁盘读取量,提高效率。
注意点:
- Join Buffer 限制:驱动表数据过大时,需分阶段加载,导致被驱动表扫描次数增加。
- 优化方法:选择数据量小、索引完善的表作为驱动表。
优化示例:
- 不推荐:
SELECT * FROM scores LEFT JOIN student ON ...
(大表驱动小表) - 推荐:
SELECT * FROM student LEFT JOIN scores ON ...
(小表驱动大表)
1.2.3. 用连接查询代替子查询
问题:
- 子查询需要多次数据库查询,常依赖临时表或内存表,效率低。
- 子查询通常无法充分利用索引。
优化方法:
- 优先使用 JOIN 查询。
- JOIN 查询直接利用索引,加速读取并降低资源消耗。
示例:
-- 子查询方式
SELECT name, department
FROM student
WHERE id IN (SELECT student_id FROM scores WHERE grade > 90);-- JOIN 查询方式(更高效)
SELECT s.name, s.department
FROM student s
JOIN scores sc ON s.id = sc.student_id
WHERE sc.grade > 90;
1.2.4. 提升 GROUP BY
的效率
问题:
- 无索引时,
GROUP BY
会对全表进行排序与分组,耗时较长。
优化方法:
- 创建索引:在
GROUP BY
的列上添加适当索引。 - 优化查询:避免子查询,尝试使用 JOIN 或 EXISTS。
- 限制结果集:通过
LIMIT
缩小返回范围。
效果对比:
- 无索引:
SELECT remarks FROM scores GROUP BY remarks;
查询耗时:4.096秒 - 添加索引后:耗时缩短至 0.001秒。
1.2.5. 批量操作
问题:
- 单条插入导致多次数据库交互,性能低下。
优化建议:
- 使用批量操作,减少数据库交互次数。
- 每批次数据量建议控制在 500 条以内,避免单次操作过大导致数据库响应缓慢。
示例:
// 单条插入
for (Record record : records) {jdbcTemplate.update("INSERT INTO table (col1, col2) VALUES (?, ?)", record.getCol1(), record.getCol2());
}// 批量插入
String sql = "INSERT INTO table (col1, col2) VALUES (?, ?)";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {public void setValues(PreparedStatement ps, int i) {Record record = records.get(i);ps.setString(1, record.getCol1());ps.setString(2, record.getCol2());}public int getBatchSize() {return records.size();}
});
1.2.6. 使用 LIMIT
优化查询
优势:
- 限制数据行数:避免查询超大量数据造成系统崩溃。
- 优化分页查询:减少不必要的全表扫描。
- 减轻网络负担:仅返回关心的数据行,提高传输效率。
分页示例:
-- 查询第一页,每页 10 条数据
SELECT * FROM scores ORDER BY id LIMIT 10 OFFSET 0;-- 查询第二页
SELECT * FROM scores ORDER BY id LIMIT 10 OFFSET 10;
注意:
- 对百万级表,
LIMIT
翻页会导致性能下降,推荐使用基于索引的优化方式:
-- 基于索引的分页
SELECT * FROM scores WHERE id > (SELECT id FROM scores ORDER BY id LIMIT 1 OFFSET 1000) LIMIT 10;
总结
优化 SQL 查询的核心思想是减少不必要的资源消耗,提高数据库的利用效率。通过避免全表扫描、使用合适的索引、小表驱动大表、批量操作和分页优化,可以显著提升系统性能。
博客主页: 总是学不会.