技术分享 | 你知道 MySQL 函数 sysdate() 与 now() 的区别么?

2023年 12月 20日 43.9k 0

作者:余振兴,爱可生 DBA 团队成员,热衷技术分享、编写技术文档。

作者:陈伟,爱可生 DBA 团队成员,负责 MySQL 日常维护及故障处理。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文约 1400 字,预计阅读需要 4 分钟。

1背景

在客户现场优化一批监控 SQL 时,发现一批 SQL 使用 sysdate()
作为统计数据的查询范围值,执行效率十分低下,查看执行计划发现不能使用到索引,而改为 now()
函数后则可以正常使用索引,以下是对该现象的分析。

内心小 ps 一下:sysdate()
的和 now()
的区别这是个⽼问题了。

2函数 sysdate 与 now 的区别

下面我们来详细了解一下函数 sysdate()
now()
的区别,我们可以去官方文档[1] 查找他们两者之间的详细说明。

根据官方说明如下:

  • now()
    函数返回的是一个常量时间,该时间为语句开始执行的时间。即当存储函数或触发器中调用到 now()
    函数时,now()
    会返回存储函数或触发器语句开始执行的时间。
  • sysdate()
    函数则返回的是该语句执行的确切时间。

下面我们通过官方提供的案例直观展现两者区别。

mysql> SELECT NOW(), SLEEP(2), NOW();
+---------------------+----------+---------------------+
| NOW()               | SLEEP(2) | NOW()               |
+---------------------+----------+---------------------+
| 2023-12-14 15:13:09 |        0 | 2023-12-14 15:13:09 |
+---------------------+----------+---------------------+
1 row in set (2.00 sec)
 
mysql> SELECT SYSDATE(), SLEEP(2), SYSDATE();
+---------------------+----------+---------------------+
| SYSDATE()           | SLEEP(2) | SYSDATE()           |
+---------------------+----------+---------------------+
| 2023-12-14 15:13:19 |        0 | 2023-12-14 15:13:21 |
+---------------------+----------+---------------------+
1 row in set (2.00 sec)

通过上面的两条 SQL 我们可以发现,当 SQL 语句两次调用 now()
函数时,前后两次 now()
函数返回的是相同的时间,而当 SQL 语句两次调用 sysdate()
函数时,前后两次 sysdate()
函数返回的时间在更新。

到这里我们根据官方文档的说明加上自己的推测大概可以知道,函数sysdate()
之所以不能使用索引是因为 sysdate()
的不确定性导致索引不能用于评估引用它的表达式。

3测试示例

以下通过示例模拟客户类似场景。

我们先创建⼀张测试表,对 create_time
字段创建索引并插入数据,观测函数 sysdate()
now()
使⽤索引的情况。

mysql> create table t1(
    ->   id int primary key auto_increment,
    ->   create_time datetime default current_timestamp,
    ->   uname varchar(20),
    ->   key idx_create_time(create_time)
    -> );
Query OK, 0 rows affected (0.02 sec)
 
mysql> insert into t1(id) values(null),(null),(null);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0
 
mysql> insert into t1(id) values(null),(null),(null);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
  
mysql> select * from t1;
+----+---------------------+-------+
| id | create_time         | uname |
+----+---------------------+-------+
|  1 | 2023-12-14 15:34:30 | NULL  |
|  2 | 2023-12-14 15:34:30 | NULL  |
|  3 | 2023-12-14 15:34:30 | NULL  |
|  4 | 2023-12-14 15:34:37 | NULL  |
|  5 | 2023-12-14 15:34:37 | NULL  |
|  6 | 2023-12-14 15:34:37 | NULL  |
+----+---------------------+-------+
6 rows in set (0.00 sec)

先来看看函数 sysdate()
使⽤索引的情况。可以发现 possible_keys
key
均为 NULL,确实使⽤不了索引。

mysql> explain select * from t1 where create_time explain select * from t1 where create_time

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论