MySQL 的 `EXPLAIN` 输出中,`filtered` 属性使用

通过以下两个 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. 添加合适索引

确保查询字段上有合适的索引,特别是 WHEREJOINORDER 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_timeend_time 上没有索引,即使 filtered 较小,也会因为扫描大量数据而影响性能。

✅ 推荐操作:

  1. 创建组合索引 (start_time, end_time)
  2. 使用 EXPLAIN 检查优化后的执行计划是否命中索引并显著降低 rows 和提高过滤效率

📌 总结

指标 理想状态 原因
filtered 越小越好 表示 WHERE 条件更精确,减少无效数据处理
rows 越小越好 扫描行数越少,性能越高
Extra 不出现 Using filesort / Using temporary 表示排序或分组未使用索引
相关推荐
倔强的石头_9 小时前
kingbase备份与恢复实战(二)—— sys_dump库级逻辑备份与恢复(Windows详细步骤)
数据库
阿巴斯甜14 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker15 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952716 小时前
Andorid Google 登录接入文档
android
黄林晴17 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android