SQL Server用SET STATISTICS TIME ON可快速查看单次执行耗时,仅对当前会话生效且须在EXEC前设置;MySQL应使用NOW(6)或SYSUTCDATETIME()而非BENCHMARK()计时;PostgreSQL推荐CLOCK_TIMESTAMP()测函数真实运行耗时。

SQL Server 中用 SET STATISTICS TIME ON 快速看单次执行耗时
开发阶段快速定位慢存储过程,最轻量的方式就是打开客户端统计开关。它不改代码、不依赖权限,直接在 SSMS 或应用连接中加两行就行:
-
SET STATISTICS TIME ON开启后,每次EXEC存储过程都会在“消息”窗口输出SQL Server Execution Times:行,含CPU time和elapsed time - 注意:只对当前会话生效,且必须在
EXEC前设置;如果过程里有SET NOCOUNT ON,不影响时间统计输出 - 常见误操作:在存储过程定义体内写
SET STATISTICS TIME ON—— 这不会生效,因为该命令不能在存储过程内执行 - 不适用于自动化监控,只是临时诊断手段;
elapsed time包含网络传输和客户端渲染开销,不是纯服务端耗时
MySQL 存储过程中记录执行时间要用 BENCHMARK() 吗?别用
想在 MySQL 存储过程里埋点计时,BENCHMARK() 是个误导性函数——它用于压测表达式重复执行次数,完全不适用于耗时测量。
- 正确做法是用
NOW(6)或SYSUTCDATETIME()(MySQL 8.0.28+)获取微秒级时间戳,前后相减得到间隔 - 示例:
SELECT TIMESTAMPDIFF(MICROSECOND, @start_time, NOW(6)) AS us_elapsed;,结果单位是微秒,除以 1000000 得秒 - 避免用
UNIX_TIMESTAMP():精度只有秒级,对毫秒级过程毫无意义 - 如果过程可能被并发调用,
@start_time必须声明为局部变量(DECLARE @start_time DATETIME(6);),不能用会话级用户变量(@start_time)——后者在嵌套调用时会被覆盖
在存储过程里写审计日志,为什么 INSERT INTO audit_log 容易拖慢主流程
把耗时记录直接塞进存储过程末尾的 INSERT,看似简单,实则埋雷。尤其当 audit_log 表没建好索引或日志量大时,主事务会卡住。
- 同步写日志会让存储过程执行时间增加 20–200ms(视磁盘 I/O 和锁竞争而定),原本 50ms 的过程可能变成 250ms
- 如果
audit_log表用了AUTO_INCREMENT主键 + 高频插入,容易引发页分裂和锁等待 - 更稳妥的做法是用异步方式:SQL Server 可走
Service Broker或写到内存表再由作业批量落库;MySQL 可用INSERT DELAYED(已弃用)或改用应用层发 MQ 消息 - 至少加个保护:用
TRY...CATCH包裹日志写入,失败时不中断主逻辑;并限制日志字段长度(比如procedure_name截断到 64 字符),避免长文本拖垮 insert 性能
PostgreSQL 函数里怎么拿到真实执行耗时,CLOCK_TIMESTAMP() 和 STATEMENT_TIMESTAMP() 选哪个
PostgreSQL 的时间函数容易混淆。STATEMENT_TIMESTAMP() 返回语句开始时间,但一个函数里多次调用它返回值相同;真正要测函数体内部耗时,得用 CLOCK_TIMESTAMP()。
-
CLOCK_TIMESTAMP()每次调用都返回当前真实时间(含微秒),适合做前后差值;clock_timestamp() - start_ts得到 interval 类型,可用EXTRACT(EPOCH FROM ...)转成秒级浮点数 - 别用
NOW():它等价于事务启动时的STATEMENT_TIMESTAMP(),在函数里反复调用也不变 - 如果函数被
SAVEPOINT或异常回滚影响,CLOCK_TIMESTAMP()不受影响,仍准确;但要注意它不包含 PL/pgSQL 解析和计划缓存时间,只算运行期 - 生产环境慎用高频打点:每毫秒调用一次
CLOCK_TIMESTAMP()本身就有开销,在循环里用要权衡是否值得
事情说清了就结束。实际部署时,最常被忽略的是日志写入路径的隔离性——审计表和业务表共用同一个表空间或磁盘,I/O 竞争会让性能埋点反成瓶颈。


















