PolarDB PostgreSQL Global Plan Cache介绍
关于 PolarDB PostgreSQL 版
PolarDB PostgreSQL 版是一款阿里云自主研发的云原生关系型数据库产品,100% 兼容 PostgreSQL,高度兼容Oracle语法;采用基于 Shared-Storage 的存储计算分离架构,具有极致弹性、毫秒级延迟、HTAP 、Ganos全空间数据处理能力和高可靠、高可用、弹性扩展等企业级数据库特性。同时,PolarDB PostgreSQL 版具有大规模并行计算能力,可以应对 OLTP 与 OLAP 混合负载。
功能介绍
PostgreSQL使用 Prepared Statement来避免 SQL 语句的多次语法解析和计划生成。主要支持的协议包含:
Simple 协议(可以在 psql 中直接测试)
Extended 协议
两种协议的基本原理类似。以下通过 simple 协议来模拟:
PREPARE s AS SELECT * FROM t;
EXECUTE t;
EXECUTE t;复制
第一次执行完 EXECUTE
以后,语法解析树(Parse Tree)和执行计划树(Plan Tree)都已经生成,第二次执行的时候无需再进行语法解析和计划生成了。但这套机制存在两个明显的问题:
Plan Cache 和 Prepare Statement 绑定,即使是两个内容完全相同的 Prepared Statement 之间也是不能共享的。比如
PREPARE s2 AS SELECT * FROM t1
不能够和s
共享任何信息。Prepared Statment 和 Backend 进程绑定,即使两个不同的连接使用完全相同的 Prepared Statement,也无法共享任何内容。
PolarDB-PG 设计了 全局执行计划缓存 Global Plan Cache(GPC),通过让不同的连接共享同一份 Plan Cache 来解决这两个问题。对于不同的 Prepared Statement 和不同的连接,只要他们的 Query Key 是一样的,那么执行计划就可以被共享。Query Key 包括的信息有:
查询文本
数据库 ID
Search Path
用户 ID
设计原理
GPC 最主要的设计是将 Plan Cache 从 Backend 进程的私有内存迁移到 Backend 进程之间的共享内存中。同时,由于 PolarDB 支持事务 DDL,所以一个 Plan Cache 可能依赖一个没有提交(自己可见别人不可见)的对象,导致 Plan Cache 不能立马写入 Global Plan Cache 中。所以 GPC 写入的时机是事务提交以后,将当前 Backend 进程私有内存中的 Plan Cache 迁移到共享内存中的 GPC 中。迁移的过程中,如果发现共享内存已满,依然可以将 Plan Cache 保留在进程的私有内存中。
所有的 Global Plan Cache 和 Local Plan Cache 拥有相同的失效条件,尽管它们的实现非常不同。在 GPC 中,所有的执行计划缓存是共享的。所以对于 A 来说不可用时,对于 B 来说可能依然可用——比如当 Search Path 发生变化时。真正的资源回收会发生在清理阶段,对于部分特殊场景,Plan Cache 的失效会立刻触发清理资源,比如当没有任何人使用这个资源时。