通过以下两个 SQL 执行计划,没有太大差异,唯有 filtered 属性数值不一样
sql
select
count(1)
from payment_log c
INNER JOIN user_relation r ON r.user_id = c.uid
left join user u on c.uid = u.id
where
( c.start_time <= '2025-12-31' AND c.start_time >= '2024-01-01'
or c.end_time <= '2025-12-31' AND c.end_time >= '2024-01-01')

sql
select
count(1)
from payment_log c
INNER JOIN user_relation r ON r.user_id = c.uid
left join user u on c.uid = u.id
where NOT (c.end_time < '2024-01-01' OR c.start_time > '2025-12-31');

在 MySQL 的 EXPLAIN
输出中,filtered
属性表示经过 WHERE 条件过滤后,预计保留的行百分比。它是一个估算值,用于帮助优化器评估查询效率。
🔍 filtered
值的意义
-
值越小越好 ✅
- 表示经过 WHERE 条件过滤后,只有较少比例的数据被保留,说明条件更"精确",能有效减少需要处理的数据量。
- 例如:
filtered=10.00
表示该表中大约有 10% 的数据满足当前查询条件。
-
值较大(接近 100)⚠️
- 表示 WHERE 条件不够精准,几乎整张表的数据都需要处理,可能导致性能问题,尤其是大表。
- 这时应考虑:
- 是否缺少合适的索引
- SQL 条件是否可以进一步优化
- 是否使用了不支持索引的操作(如函数、通配符开头的 LIKE)
📌 示例解释
假设你看到如下 EXPLAIN
输出:
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------+
| 1 | SIMPLE | c | NULL | ALL | NULL | NULL | NULL | NULL | 583189 | 11.11 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+----------------+
rows=583189
:表示 MySQL 预计要扫描约 58 万行数据。filtered=11.11
:表示最终只保留约 11% 的数据(即约 6.4 万行),虽然这个值不算高,但因为扫描基数太大,整体性能仍然可能较差。
✅ 如何提升 filtered
的效率?
1. 添加合适索引
确保查询字段上有合适的索引,特别是 WHERE
、JOIN
和 ORDER BY
中使用的字段。
2. 优化 SQL 写法
避免全表扫描,改写复杂的 OR 条件为等效但更易优化的形式(如 NOT (end_time < x OR start_time > y)
)。
3. 使用覆盖索引(Covering Index)
创建包含查询所需所有字段的索引,避免回表查询。
4. 减少不必要的 JOIN 或子查询
有时可以通过提前过滤或重写查询逻辑来减少数据处理量。
🧪 实际建议
根据你之前的 SQL 查询和执行计划:
sql
AND NOT (c.end_time < #{interviewDate1} OR c.start_time > #{interviewDate2})
若 start_time
和 end_time
上没有索引,即使 filtered
较小,也会因为扫描大量数据而影响性能。
✅ 推荐操作:
- 创建组合索引
(start_time, end_time)
- 使用
EXPLAIN
检查优化后的执行计划是否命中索引并显著降低rows
和提高过滤效率
📌 总结
指标 | 理想状态 | 原因 |
---|---|---|
filtered |
越小越好 | 表示 WHERE 条件更精确,减少无效数据处理 |
rows |
越小越好 | 扫描行数越少,性能越高 |
Extra |
不出现 Using filesort / Using temporary |
表示排序或分组未使用索引 |