知识卡片

存储过程省下的是网络与解析开销,代价是复制诡异和缓存浪费

普通读书笔记卡

内容

存储过程/函数是否”更快”不能一概而论,而要看它省下了什么、又付出了 什么。它真正的性能收益来自省掉网络往返和解析/优化开销:一个存储过程 调用可以在服务器内部完成本来需要很多次小查询才能做的事,如果这些小 查询本身很轻,那么每次查询固有的网络通信、SQL解析、优化器开销占比 就会很高,把它们打包进一次存储过程调用能显著摊薄这部分固定成本—— 书中一百万行数据的写入基准测试里,存储过程用101秒完成,客户端逐条 插入要279秒,差距主要就来自省下的网络和解析开销,而不是”存储过程本身 执行更快”。但这个收益是有代价的,且代价不体现在单次调用的响应时间上: 优化器无法用DETERMINISTIC这类声明去优化同一查询里多次调用存储函数 的情况,也无法评估存储函数本身的执行成本,这意味着优化器在涉及存储 代码时基本是”盲选”执行计划;执行计划缓存是按连接维度隔离的,多个连接 调用同一个存储过程时,同一份执行计划会被反复独立缓存,白白浪费缓存 空间;存储程序和基于语句的复制是”诡异组合”——如果直接复制对存储过程 的调用而不是它实际改变的数据,主备之间执行结果可能不一致,这也是 MySQL后来引入基于行的复制来缓解这个问题的原因之一。这说明”要不要用 存储过程”本质上是在”减少单次交互的固定开销”和”给优化器、复制、缓存 系统增加不透明的黑盒”之间做权衡,而不是简单的”存储过程天生快或慢”。

参考来源

- 位置:《高性能MySQL:第3版》第7章"MySQL高级特性"7.4.1节"存储过程和 函数"(源文件:_epub-src/OEBPS/Text/part0014.xhtml) - 结论依据:原文明确"优化器无法使用关键字DETERMINISTIC来优化单个 查询中多次调用存储函数的情况。优化器无法评估存储函数的执行成本。 每个连接都有独立的存储过程的执行计划缓存……存储程序和复制是一组 诡异组合",并给出存储过程101秒对比客户端逐条插入279秒的基准测试 数据,直接支撑"收益来自省下网络/解析开销,代价是优化器盲选/缓存 浪费/复制风险"的结论。 - 原始内容:可以看到存储过程要快很多,很大程度因为它无须网络通信 开销、解析开销和优化器开销等……存储程序和复制是一组诡异组合。