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 表示排序或分组未使用索引
相关推荐
编程乐学42 分钟前
网络资源模板--基于Android Studio 实现的运动场馆预约
android·android studio·大作业·移动端开发·安卓移动开发·场馆预约·运动场馆预约
编程乐学42 分钟前
网络资源模板--基于Android Studio 实现的画板App
android·android studio·画图·移动端开发·画板·安卓大作业
转身後 默落3 小时前
01.Redis 概述
数据库·redis·缓存
你的人类朋友5 小时前
❤️‍🔥为了省内存选择sqlite,代价是什么
数据库·后端·sqlite
还是鼠鼠5 小时前
tlias智能学习辅助系统--SpringAOP-进阶-通知顺序
java·后端·mysql·spring·mybatis·springboot
飞翔的佩奇5 小时前
基于SpringBoot+MyBatis+MySQL+VUE实现的名城小区物业管理系统(附源码+数据库+毕业论文+开题报告+部署教程+配套软件)
数据库·vue.js·spring boot·mysql·毕业设计·mybatis·小区物业管理系统
一笑的小酒馆5 小时前
Android15适配和Google上架问题
android
小白不想白a5 小时前
【MySQL】MySQL的安全风险与安装安全风险
linux·数据库·mysql·安全
折翼的恶魔6 小时前
SQL148 返回产品名称和每一项产品的总订单数
数据库
技术不支持6 小时前
Qt Creator 11.0.3 语法高亮bug问题
java·服务器·数据库·qt·bug