sql优化思路
文章目录
- 1、善用分析工具
- 2、Extra可能的性能问题关键提示
- 3、filtered可能的性能问题关键提示
- 4、rows可能的性能问题关键提示
1、善用分析工具
使用EXPLAIN+sql分析sql大致执行情况,分析究竟是哪一步拖慢执行速度,定位问题
EXPLAIN SELECT u.username,o.order_id,o.amount,p.product_name,c.category_name
FROM users u
JOIN orders o ON u.user_id = o.user_id
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
JOIN categories c ON p.category_id = c.category_id
WHERE u.register_date >= '2023-01-01'AND o.order_date BETWEEN '2023-01-01' AND '2023-12-31'AND o.amount > 1000
ORDER BY o.order_date DESC
LIMIT 100;+----+-------------+-------+------------+--------+---------------+---------+---------+----------------------+---------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+--------+---------------+---------+---------+----------------------+---------+----------+----------------------------------------------------+
| 1 | SIMPLE | u | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 50000 | 100.00 | Using index condition; Using temporary; Using filesort |
| 1 | SIMPLE | o | NULL | ref | idx_user_id | idx_user_id | 5 | db.u.user_id | 10 | 33.33 | Using where |
| 1 | SIMPLE | oi | NULL | ref | idx_order_id | idx_order_id | 4 | db.o.order_id | 5 | 100.00 | NULL |
| 1 | SIMPLE | p | NULL | eq_ref | PRIMARY | PRIMARY | 4 | db.oi.product_id | 1 | 100.00 | NULL |
| 1 | SIMPLE | c | NULL | eq_ref | PRIMARY | PRIMARY | 4 | db.p.category_id | 1 | 100.00 | NULL |
+----+-------------+-------+------------+--------+---------------+---------+---------+----------------------+---------+----------+----------------------------------------------------+
2、Extra可能的性能问题关键提示
- Using filesort
含义:无法利用索引排序,需在内存 / 磁盘中对结果集排序。
示例:若 ORDER BY 字段无索引,会触发此提示,大数据量时耗时极长。 - Using where; Using join buffer
含义:表关联时未使用索引,通过 “连接缓冲区” 暴力匹配(类似嵌套循环)。
示例:大表 orders 与 users 关联时无 user_id 索引,会导致全表扫描 + 缓冲区匹配,效率极低。 - Using index condition
含义:索引只能部分过滤数据,需回表查询剩余条件(“索引下推” 优化未完全生效)。
示例:users 表用主键索引范围扫描 register_date,但 register_date 本身无索引,需回表确认条件。 - Using full scan(type 为 ALL)
含义:全表扫描,未使用任何索引。
示例:products 表无 category_id 索引,关联时扫描全表 50,000 行,而非通过索引定位。 - Range checked for each record (index map: 0x1)
含义:数据库无法确定合适的索引,需为每行记录单独评估索引,效率极低。
示例:多表关联时,外键字段索引缺失但存在其他多个索引,无法判断使用哪个索引(部分索引)达到最佳查询效果,导致逐行判断索引可用性。
3、filtered可能的性能问题关键提示
filtered 表示经过该表的 WHERE 条件过滤后,剩余行占预估扫描行数的百分比(范围 0-100),这里的过滤值得是Service层的过滤占比,存贮引擎的过滤不算,所以这个数值越高越好,若都是100,说明所有表都是用了索引直接查出数据,没有在service使用where进行过滤
4、rows可能的性能问题关键提示
rows 表示数据库预估扫描的行数(非精确值,基于统计信息),用于评估查询开销,使得小表驱动大表,例如:
users 表 rows=50000:预估符合 register_date >= ‘2023-01-01’ 的行数为 50,000 行。
orders 表 rows=10:对于每个 users 表的行,预估匹配 10 行 orders 表数据(即平均每个用户有 10 个订单)。
order_items 表 rows=5:对于每个 orders 表的行,预估匹配 5 行 order_items 数据(即平均每个订单有 5 个商品)。
*文章参考:
sql优化优化实战案例
javaGuide-索引下推