MySQL中无法用NOW()或SYSDATE()直接测SQL执行耗时,因二者均不捕获语句实际运行区间;需客户端打点计时或启用profiling(SHOW PROFILES),但后者已废弃且不包含锁等待等阻塞时间。

MySQL 中用 NOW() 和 SYSDATE() 测时间差会出错
直接相减 NOW() 和 SYSDATE() 得不到执行耗时,因为两者都返回「当前时间」,且在语句开始时就已求值(NOW())或执行时动态求值(SYSDATE()),但无法捕获语句内部实际运行区间。更关键的是:SQL 本身不提供“语句级计时钩子”,不能像程序语言那样在开头结尾插桩。
用 BENCHMARK() 只能测函数调用开销,不是 SQL 执行时间
BENCHMARK() 的作用是重复执行某个表达式(比如 BENCHMARK(1000000, MD5('test'))),用来压测函数性能,但它不包裹你的 SELECT 或 UPDATE 语句,也不记录真实查询的解析、执行、网络往返耗时。它测的是纯计算,和你关心的「这条 UPDATE 花了多久」完全无关。
真正可行的方案只有客户端计时 + SHOW PROFILES(MySQL 5.7+ 已废弃,但仍有用)
MySQL 服务端不暴露单条语句的精确执行耗时给 SQL 层,必须靠外部配合:
- 在应用代码里用
time.time()(Python)、System.nanoTime()(Java)等在发送 SQL 前后打点,减法得毫秒级耗时(含网络、序列化、驱动开销) - 开启
profiling(仅开发/调试):SET profiling = 1;<br>SELECT * FROM users WHERE id = 123;<br>SHOW PROFILES;
输出里Duration列才是服务器侧实际执行时间(单位秒,精度到微秒) - 注意
SHOW PROFILES不显示锁等待、磁盘 I/O 等阻塞时间;若需完整链路,得结合performance_schema.events_statements_history_long
PostgreSQL 和 SQLite 怎么办?
PostgreSQL 支持 \timing on(psql 客户端命令),它在客户端侧计时,结果最贴近用户感知;SQLite 没内置计时,只能靠 shell 的 time sqlite3 db "SELECT ..." 或应用层手动打点。没有数据库能在纯 SQL 里写出 start = now(); ...; end = now(); select end - start 这种逻辑——SQL 不是过程式语言,没有变量赋值和顺序执行保障。
最容易被忽略的是:所谓“SQL 执行时间”其实包含至少三层耗时(网络传输、服务端排队、引擎执行),而绝大多数人只想要最后一层,但又没意识到前两层在监控里往往占比更高。

















