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 表示排序或分组未使用索引
相关推荐
m***923810 小时前
【SQL】MySQL中的字符串处理函数:concat 函数拼接字符串,COALESCE函数处理NULL字符串
数据库·sql·mysql
!停10 小时前
VS实用调试技巧
数据库
TracyCoder12311 小时前
MySQL 实战宝典(八):Java后端MySQL分库分表工具解析与选型秘籍
java·开发语言·mysql
8***235511 小时前
在Django中安装、配置、使用CKEditor5,并将CKEditor5录入的文章展现出来,实现一个简单博客网站的功能
数据库·django·sqlite
Aileen_0v012 小时前
【Gemini3.0的国内use教程】
android·人工智能·算法·开源·mariadb
Token_w12 小时前
openGauss:全密态数据库的金融级安全实践
数据库·安全·金融
合作小小程序员小小店12 小时前
图书管理系统,基于winform+sql sever,开发语言c#,数据库mysql
开发语言·数据库·sql·microsoft·c#
ss27312 小时前
020:共享锁深度解析:从AQS原理到高并发实践
数据库·redis·缓存
字节拾光录12 小时前
手机号存储避坑指南:从20亿级数据库实践看,为什么VARCHAR才是终极答案
java·数据库·oracle
浩浩的代码花园13 小时前
自研端侧推理模型实测效果展示
android·深度学习·计算机视觉·端智能