深入浅出PostgreSQL性能调优
postgresql性能 深入浅出 调优
2023-06-13 09:17:21 时间
PostgreSQL
性能调优概览
PostgreSQL
参数类型
struct config_generic
定义了所有PG参数的通用结构;struct config_{int/real/string/bool}
在struct config_generic
之上进行分组定义了不同数据类型的参数类型
深入PostgreSQL
性能参数
shared_buffers
参数
PostgreSQL
中按照参数的类型(int/bool/string/real)等类型进行分组进行解析。但是针对shared_buffers
在配置文件中可以内存大小(单位可是是KB/MB/GB/TB)。在shared_buffers
定义在struct config_int
中。NBuffers
全局变量根据shared_buffers
大小计算出page
的个数,根据这个来初始化shared buffer pool
static struct config_int ConfigureNamesInt[] ={
// shared_buffers定义
{
// 设置shared_buffers的参数名称、参数级别、参数资源类型
{"shared_buffers", PGC_POSTMASTER, RESOURCES_MEM,
gettext_noop("Sets the number of shared memory buffers used by the server."),
NULL,
GUC_UNIT_BLOCKS },
// 根据shared_buffers设置的内存大小,结算出缓存多少个page的个数,然后在申请资源进行初始化整个buffer pool
// 参数对应的PG内部的单位是数据页,比如设置100M,则最终的shared_buffers在PG内部对应参数绑定的是(100*1024/(数据页/1024))
&NBuffers,
1024, 16, INT_MAX / 2,
NULL, NULL, NULL
},}
shared_buffer
的初始化链路如下,从这里可以看出shared_buffer
不能再PG运行期间动态进行调整,调整整个参数后需要重启PostgreSQL
服务。这里有一个优化调整shared_buffer
不重启的思路,是否可以把shared buffer pool
改变为多个子池,整个shared pool
包含最大个子池指针数组,动态调整值需要再对应的数组指针下标申请空间,可以这么做但是需要考虑资源互斥、脏页刷新等。
void InitBufferPool(void){
bool foundBufs,
foundDescs,
foundIOCV,
foundBufCkpt;
// buffer pool 中page的header申请
BufferDescriptors = (BufferDescPadded *)
ShmemInitStruct("Buffer Descriptors",
NBuffers * sizeof(BufferDescPadded),
&foundDescs);
// buffer pool中数据块空间申请
BufferBlocks = (char *)
ShmemInitStruct("Buffer Blocks",
NBuffers * (Size) BLCKSZ, &foundBufs);
/* Align condition variables to cacheline boundary. */
BufferIOCVArray = (ConditionVariableMinimallyPadded *)
ShmemInitStruct("Buffer IO Condition Variables",
NBuffers * sizeof(ConditionVariableMinimallyPadded),
&foundIOCV);
// 用来排序已经做了checkpoint的page head的数组
CkptBufferIds = (CkptSortItem *)
ShmemInitStruct("Checkpoint BufferIds",
NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
if (foundDescs || foundBufs || foundIOCV || foundBufCkpt)
{
Assert(foundDescs && foundBufs && foundIOCV && foundBufCkpt);
}
else
{
int i;
// 初始化buffer pool中的每个page header
for (i = 0; i < NBuffers; i++)
{
BufferDesc *buf = GetBufferDescriptor(i);
CLEAR_BUFFERTAG(buf->tag);
pg_atomic_init_u32(&buf->state, 0);
buf->wait_backend_pid = 0;
// 设定page id
buf->buf_id = i;
// 链接下一个page header
buf->freeNext = i + 1;
LWLockInitialize(BufferDescriptorGetContentLock(buf),
LWTRANCHE_BUFFER_CONTENT);
ConditionVariableInit(BufferDescriptorGetIOCV(buf));
}
/* Correct last entry of linked list */
GetBufferDescriptor(NBuffers - 1)->freeNext = FREENEXT_END_OF_LIST;
}
// 初始化shared pool剩下的事务
StrategyInitialize(!foundDescs);
// 初始化后端文件flush的上下文
WritebackContextInit(&BackendWritebackContext,
&backend_flush_after);}
wal_buffers
参数
PostgreSQL
中按照参数的类型(int/bool/string/real)等类型进行分组进行解析。但是针对wal_buffers
在配置文件中可以内存大小(单位可是是KB/MB/GB/TB)。定义如下
static struct config_int ConfigureNamesInt[] ={
// wal_buffers定义
{
// 参数绑定
{"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS,
gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."),
NULL,
// 设置单位
GUC_UNIT_XBLOCKS },
// 绑定wal_buffers对应的变量
&XLOGbuffers,
-1, -1, (INT_MAX / XLOG_BLCKSZ),
check_wal_buffers, NULL, NULL
},}
wal log buffer
初始化过程如下,同样的这个参数不能再PostgreSQL
运行期动态更改,如果更改必须重启PostgreSQL
服务
void XLOGShmemInit(void){
bool foundCFile,
foundXLog;
char *allocptr;
int i;
ControlFileData *localControlFile;// 如果编译PG时候有带有WAL_DEBUG的编译,可以在PG中进行wal 日志输出的Debug#ifdef WAL_DEBUG
// 创建wal debug的上下文和内存初始化
if (walDebugCxt == NULL)
{
walDebugCxt = AllocSetContextCreate(TopMemoryContext,
"WAL Debug",
ALLOCSET_DEFAULT_SIZES);
MemoryContextAllowInCriticalSection(walDebugCxt, true);
}#endif
// 获取wal 日志文件的控制文件
XLogCtl = (XLogCtlData *)
ShmemInitStruct("XLOG Ctl", XLOGShmemSize(), &foundXLog);
localControlFile = ControlFile;
ControlFile = (ControlFileData *)
ShmemInitStruct("Control File", sizeof(ControlFileData), &foundCFile);
if (foundCFile || foundXLog)
{
/* both should be present or neither */
Assert(foundCFile && foundXLog);
/* Initialize local copy of WALInsertLocks */
WALInsertLocks = XLogCtl->Insert.WALInsertLocks;
if (localControlFile)
pfree(localControlFile);
return;
}
memset(XLogCtl, 0, sizeof(XLogCtlData));
// 如果存在本地的控制文件读取然后初始化到内存的控制文件结构中
if (localControlFile)
{
memcpy(ControlFile, localControlFile, sizeof(ControlFileData));
pfree(localControlFile);
}
// 重置内存控制文件中的xlblocks
allocptr = ((char *) XLogCtl) + sizeof(XLogCtlData);
XLogCtl->xlblocks = (XLogRecPtr *) allocptr;
// 重置了xlog控制文件中的wal指针缓存区
memset(XLogCtl->xlblocks, 0, sizeof(XLogRecPtr) * XLOGbuffers);
allocptr += sizeof(XLogRecPtr) * XLOGbuffers;
/* WAL insertion locks. Ensure they're aligned to the full padded size */
allocptr += sizeof(WALInsertLockPadded) -
((uintptr_t) allocptr) % sizeof(WALInsertLockPadded);
WALInsertLocks = XLogCtl->Insert.WALInsertLocks =
(WALInsertLockPadded *) allocptr;
allocptr += sizeof(WALInsertLockPadded) * NUM_XLOGINSERT_LOCKS;
for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
{
LWLockInitialize(&WALInsertLocks[i].l.lock, LWTRANCHE_WAL_INSERT);
WALInsertLocks[i].l.insertingAt = InvalidXLogRecPtr;
WALInsertLocks[i].l.lastImportantAt = InvalidXLogRecPtr;
}
// 重置日志page缓冲区
allocptr = (char *) TYPEALIGN(XLOG_BLCKSZ, allocptr);
XLogCtl->pages = allocptr;
memset(XLogCtl->pages, 0, (Size) XLOG_BLCKSZ * XLOGbuffers);
// 完成后续日志控制结构的剩余结构初始化
XLogCtl->XLogCacheBlck = XLOGbuffers - 1;
XLogCtl->SharedRecoveryState = RECOVERY_STATE_CRASH;
XLogCtl->SharedHotStandbyActive = false;
XLogCtl->SharedPromoteIsTriggered = false;
XLogCtl->WalWriterSleeping = false;
SpinLockInit(&XLogCtl->Insert.insertpos_lck);
SpinLockInit(&XLogCtl->info_lck);
SpinLockInit(&XLogCtl->ulsn_lck);
InitSharedLatch(&XLogCtl->recoveryWakeupLatch);
ConditionVariableInit(&XLogCtl->recoveryNotPausedCV);}
相关文章
- POSTGRESQL 压力测试结果与 POSTGRESQL CPU OR 内存 提升性能提升大
- Postgresql源码(93)Postgresql函数内事务控制实现原理(附带Oracle对比)
- PostgreSQL数据库开发基础 之 单引号与双引号用法详解
- 快速解决PostgreSQL中的Permission denied问题
- 使用Postgresql 实现快速插入测试数据
- PostgreSQL 22P03: invalid_binary_representation 报错 故障修复 远程处理
- PostgreSQL 行排序详解数据库
- 对比对比深度:PostgreSQL与Oracle之间的差异(postgresql和oracle)
- 写PostgreSQL操作指南:读写技巧(postgresql怎么读)
- 优化PostgreSQL内核优化:提升数据库性能的必经之路(postgresql内核)
- 请聆听:Postgresql发音(postgresql发音)
- 使用Postgresql可视化工具轻松访问数据库(postgresql可视化工具)
- 招聘PostgreSQL攻城狮:让你的技能大放异彩(postgresql招聘)
- 的性能优势Postgresql在性能方面的优势——德哥的深度解读(德哥postgresql)
- 如何简单快速地安装PostgreSQL在Linux系统上(linux安装postgresql)
- 深入解析PostgreSQL扩展:优化数据库性能与拓展功能(postgresql扩展)
- PostgreSQL拼接技巧:实现高效数据整合(postgresql拼接)
- 编译PostgreSQL:一步一步实现数据库功能(postgresql编译)
- PostgreSQL 掌握精妙的数据类型(postgresql类型)
- 深入了解 PostgreSQL 数据库结构(postgresql结构)
- 管理PostgreSQL:优化内存管理提升数据库性能(postgresql内存)
- PHP读取Postgresql中的数组