1、PostgreSQL中DETOAST操作缓存的实现分享人:廖书楠场景引入需求分析详细设计性能测试1234目录directory01场景引入场景引入1.1PostgreSQL中的DETOAST操作完整的大尺寸字段值(2KB).压缩和拆分分片1TOAST操作解压缩和重拼接DETOAST操作当一次查询中多次涉及一个大尺寸字段的读取时,需要反复执行DETOAST操作,极其费时分片2分片3分片4分片51.2实际场景在某次紧急排查中,为了找出满足特定条件的告警数据,需要执行以下SQL:SELECT value FROM ZENAP_FM _ACTIVEALARM WHERE(value-alarmpath
2、-pathids ae381dea-1d16-4b2c-83f8-2db8fc68edb6“OR value-alarmpath-pathids 103ce679-ba2a-4db1-9d17-fdcd1614ef55“-.中间省略693条OR子句OR value-alarmpath-pathids d4b9bd96-9036-4344-a1b3-8571b0205d1b“)ORDER BY value-servertime DESC,value-id DESC LIMIT 1000 OFFSET 0;在某现实生产环境下的告警日志表:对于表中的每条value记录,都需要重复执行696次DETO
3、AST操作,极其费时1.3解决方案实现面向DETOAST操作的缓存:在每次执行完DETOAST操作后将结果缓存起来,后续重复访问直接从缓存中读取,无需执行耗时的DETOAST操作,降低CPU开销。在缓存中?读取是直接返回执行DETOAST否02需求分析需求分析2.1DETOAST缓存池需求分析置换策略尺寸分布TOAST字段是变长字段,其尺寸差异较大,不能采用固定大小的缓存块1多进程并发变长字段TOAST字段的尺寸分布是无法预先确定的,如果将缓存块的尺寸和数量设置为固定值,可能会导致利用率低,带来较大的空间浪费需要面对多种不同的查询场景,不宜采取单一置换策略多进程并发读取时,需考虑缓存的跨进程同
4、步问题2341.采用多级缓存链表+极大缓存区的设计3.动态置换策略机制,支持多种不同的置换策略1.变长字段2.尺寸分布3.置换策略4.多进程并发2.2设计方案03详细设计详细设计3.1总体架构设计DETOAST缓存池header0header9datadatadataheader0header9datadatadatausedLists:多级已用链表freeLists:多级空闲链表extCache:极大缓存区dataHash表映射3.2多级缓存链表header0header9datadatadataheader1datadatadata多级缓存链表:多级缓存链表是缓存池的核心数据结构。参考了P
5、ostgreSQL中AllocSetContext的实现,多级链表由多个双向链表组成,每个双向链表中存放不同尺寸的缓存块,大小分别为2KB、4KB、8KB、.、512KB、1MB(第i级链表中每个缓存块的大小为2KB);同时,每个双向链表的链表头之间也通过指针进行连接,从而形成多级链表。3.2多级缓存链表在DETOAST缓存池中有两个多级缓存链表,分别是usedLists和freeLists,其中:usedLists称为已用链表,用于存放已使用的缓存块;freeLists称为空闲链表,用来存放空闲缓存块;在运行过程中,当缓存池接收到插入TOAST字段值的请求时,首先从freeLists中取出一
6、块尺寸合适的空闲缓存块,接着将TOAST字段值写入到块中,然后将该缓存块插入到usedLists中。多级空闲链表多级已用链表取出空闲缓存块插入写入字段值3.3极大缓存区极大缓存区:为了应对极少数尺寸极大、多级缓存链表的最大缓存块也无法容纳的TOAST字段值而设计。dataTOAST字段值试图插入到多级缓存链表中插入到极大缓存区中失败,尺寸超过缓存块大小上限3.4置换策略模块设计参考Redis中的置换策略模块设计,支持多种不同的置换策略,允许在运行时动态指定;将置换策略设置为缓存池内部的一个结构体,包括一系列的辅助数