You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL日期查询预估行数差异疑问:为何结果差近一倍?

为什么两个逻辑看似等价的MySQL查询,EXPLAIN预估行数差近一倍?

首先咱们得戳破一个误区:这两个WHERE条件其实逻辑并不等价,这正是预估行数差异的核心原因。

让我们拆解两个条件的实际覆盖范围:

  • 第一个查询的条件是让start_datetime介于2019-08-28 00:00:00和2019-08-29 23:59:59,完整覆盖了48小时(整整两天)。
  • 第二个查询的条件是让start_datetime介于2019-08-28和2019-08-29。这里要注意MySQL的隐式类型转换规则:当DATE类型的值和DATETIME类型的列比较时,MySQL会自动把DATE值转换成DATETIME类型的YYYY-MM-DD 00:00:00。所以第二个条件的实际上限是2019-08-29 00:00:00,只覆盖了24小时左右(从28号0点到29号0点)。

再看EXPLAIN的预估行数逻辑:
MySQL查询优化器是基于索引的统计信息来估算范围查询的行数的。第一个查询覆盖的时间范围刚好是第二个的两倍,所以预估行数接近一倍完全符合逻辑。

你可以通过执行实际的COUNT查询验证这一点:

-- 第一个条件的实际行数
select count(*) from game_instance where start_datetime between STR_TO_DATE(CONCAT(DATE_SUB(CURDATE(), INTERVAL 2 DAY), ' ', '00:00:00'), '%Y-%m-%d %H:%i:%s') and STR_TO_DATE(CONCAT(DATE_SUB(CURDATE(), INTERVAL 1 DAY), ' ', '23:59:59'), '%Y-%m-%d %H:%i:%s');

-- 第二个条件的实际行数
select count(*) from game_instance where start_datetime between DATE_SUB(CURDATE(), INTERVAL 2 DAY) and DATE_SUB(CURDATE(), INTERVAL 1 DAY);

大概率会发现第一个查询的实际行数是第二个的两倍左右,和EXPLAIN的预估结果一致。

最后补充个小建议:如果想让第二个条件和第一个等价,需要把上限调整为包含当天最后一秒,比如写成DATE_ADD(DATE_SUB(CURDATE(), INTERVAL 1 DAY), INTERVAL 86399 SECOND),这样就能覆盖到目标日期的23:59:59了。

内容的提问来源于stack exchange,提问作者j4nd3r53n

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:14:32