MySQL 时间函数 sysdate () 与 now ()
一、生产环境的性能疑云:从一次 SQL 优化说起
在某客户的监控系统优化中,发现一批查询因使用
sysdate()导致索引失效,全表扫描使得 SQL 响应时间飙升至秒级。当将条件中的sysdate()替换为now()后,执行计划立即命中索引,查询效率提升 10 倍以上。这一现象的核心,源于 MySQL 对这两个时间函数的底层处理逻辑差异。二、时间获取机制:常量 vs 动态的本质区别
1. now ():语句级常量时间
now()在 SQL 语句开始执行时获取时间戳,并将其作为常量贯穿整个语句执行周期。即使语句中多次调用now(),返回值始终为初始时间。例如:SELECT NOW(), SLEEP(2), NOW();
-- 输出:2023-12-14 15:13:09 | 0 | 2023-12-14 15:13:09
这种 “一次获取,全程复用” 的机制,使优化器能在解析阶段将
now()视为已知常量。2. sysdate ():实时动态时间
sysdate()则在每次调用时实时获取系统时间,因此同一语句中多次调用会返回不同值:SELECT SYSDATE(), SLEEP(2), SYSDATE();
-- 输出:2023-12-14 15:13:19 | 0 | 2023-12-14 15:13:21
这种动态性导致优化器无法在解析阶段确定其值,进而影响索引优化策略。
三、索引失效之谜:动态性引发的执行计划差异
为验证两者对索引的影响,创建测试表
t1(含create_time索引)并执行查询:1. sysdate () 导致全表扫描
EXPLAIN SELECT * FROM t1 WHERE create_time < sysdate();
-- 执行计划:type=ALL(全表扫描),possible_keys=NULL
原因在于
sysdate()的动态性使优化器无法将create_time < sysdate()转化为可利用索引的范围条件,只能遍历全表。2. now () 触发索引范围查询
EXPLAIN SELECT * FROM t1 WHERE create_time < now();
-- 执行计划:type=range,key=idx_create_time
now()作为常量被优化器解析为具体时间值(如'2023-12-14 15:48:39'),从而将条件转化为create_time < 常量,可通过索引快速定位范围。四、优化器视角:从 trace 看底层处理逻辑
通过 MySQL 的查询优化追踪(trace)可发现:
- 处理 now () 时,优化器在
rows_estimation阶段将now()的值转换为确定常量(如'2023-12-14 15:48:39'),并基于该常量计算索引范围扫描的成本,最终选择索引执行计划。 - 处理 sysdate () 时,优化器无法获取其具体值,在
range_analysis中判定索引 “usable: true”,但因条件无法转化为固定范围,最终只能选择全表扫描(access_type: scan)。 
五、实践指南:何时选择何种函数
1. 优先使用 now () 的场景
- 时间范围查询(如
WHERE create_time BETWEEN now()-INTERVAL 1 DAY AND now()) - 需要语句内时间一致性的场景(如事务内多条语句需基于同一时间点)
 
2. 必须使用 sysdate () 的场景
- 需获取语句执行中实时时间(如记录操作耗时)
 - 触发器中需要精确记录触发时刻(而非语句开始时刻)
 
3. 性能优化建议
- 避免在索引字段的查询条件中直接使用 sysdate (),可通过变量缓存时间值:
SET @now = sysdate(); SELECT * FROM t1 WHERE create_time < @now; -- 此时@now为常量,可触发索引 - 定期分析包含时间函数的 SQL 执行计划,通过
EXPLAIN FORMAT=JSON查看优化器对时间值的处理方式。 
六、版本差异与延伸思考
在 MySQL 8.0 中,
now()与sysdate()的底层实现差异进一步明确:now()对应TIMESTAMP类型的语句开始时间sysdate()对应SYSDATE()函数的实时系统时间
值得注意的是,在存储过程或触发器中,
now()的行为可能与预期不同 —— 它返回的是存储过程 / 触发器被调用时的时间,而非每次执行时的时间。此时若需实时时间,必须显式使用sysdate()。结语
sysdate () 与 now () 的细微差异,在生产环境中可能引发显著的性能波动。理解两者的底层逻辑后,开发者可根据场景选择合适的函数,并通过变量缓存等技巧规避动态时间导致的索引失效问题。这一案例也印证了 MySQL 优化中的核心原则:优化器对确定性表达式的处理效率远高于动态表达式。
                    
                
                
            
        
浙公网安备 33010602011771号