设置segment_buffers
segment_buffers是用来设置段页式元数据页的内存大小的参数,为了提高性能需要设置足够大的buffer,保证活跃表的元数据页面都能缓存在buffer中,不被频繁置换。
hashbucket表基于段页式存储格式,由1024个bucket桶组成,每一个bucket桶由一组bucket段页式文件管理。其中DN上元数据页面主要包括bucket1号文件和段页式1号文件两部分,CN上主要为段页式1号文件。
bucket1号文件的元数据页面
以下表或索引都会在每个bucket的1号文件中申请3个页面(main_fork、fsm_fork、vm_fork)作为hashbucket元数据页面:
- 表:普通表、分区表的每个分区、toast表、toast索引。
- LBI索引:普通表的LBI索引、GLOBAL的LBI索引、LOCAL每个分区的LBI索引。
可以按照以下公式估算页面数:
单个DN上bucket桶个数 * 3 * ((普通表个数 + 分区表的分区个数) * 3 + LBI索引个数 + LOCAL的LBI索引分区个数)
公式中第一个3表示main_fork、fsm_fork、vm_fork,第二个3表示表、toast表、toast索引。为方便计算假设用户表都有toast表和toast索引。
段页式1号文件的元数据页面
每个表或索引都会在段页式1号文件中申请1个页面作为元数据页面,可以按照以下公式估算页面数:
(普通表个数 + 分区表的分区个数) * 3 + 索引个数 + LOCAL索引分区个数
公式中的3表示表、toast表、toast索引,为方便计算假设用户表都有toast表和toast索引。
segment_buffers设置示例
假设活跃表共10张,其中4张普通表,6张分区表。普通表共8个索引,其中5个是LBI索引。 每个分区表都有20个分区,分区表共12个索引,其中7个是LOCAL的LBI索引。假设集群有3个DN分片,每个DN上分配342个bucket桶。
估算元数据页面:
- bucket1号文件:
单个DN上bucket桶个数 * 3 * ((普通表个数 + 分区表的分区个数) * 3 + 普通表LBI索引个数 + LOCAL的LBI索引分区个数) = 342 * 3 * ((4 + 6 * 20) * 3 + 5 + 7 * 20) = 530442个页面 ≈ 4144MB
- 段页式1号文件:
(普通表个数 + 分区表的分区个数) * 3 + 索引个数 + LOCAL索引分区个数 = (4 + 6 * 20) * 3 + (8 + 12) + 7 * 20 = 532个页面 ≈ 4MB
此示例中在内存足够的情况下,建议每个DN的 segment_buffers 设置为不小于 4148MB,每个CN的segment_buffers不小于4MB。
- 建议设置segment_buffers大于等于活跃表的元数据页面总空间,避免元数据页面buffer置换导致性能劣化。
- hashbucket表尤其是分区表占用的元数据页面比较多,建议根据以上公式估算并设置segment_buffers。
- 注意内存设置应满足条件:data_replicate_buffer_size + segment_buffers + shared_buffers + wal_buffers + temp_buffers + maintenance_work_mem + work_mem + query_mem + (备机)wal_receiver_buffer_size < max_process_memory < 物理机内存大小。在物理机总内存大小不足的情况下,建议segment_buffers设置为(shared_buffers的参考值 * 估算的元数据量 / 总数据量)。
- 一些DDL操作需要加载大量元数据页面,如 \d+ 操作会加载所有表的元数据页面,元数据页面第一次加载到缓冲区中时或segment_buffers参数大小不足时会导致执行时间较长。
- 设置segment_buffers参数后需要重启集群才生效。