ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

KingbaseES数据库内存管理实战:从SGA到PGA的调优之路

KingbaseES数据库内存管理实战:从SGA到PGA的调优之路 干了这么多年的数据库运维我发现个挺有意思的事儿。很多DBA聊起SQL调优都头头是道但一问到内存怎么配置就开始支支吾吾了。其实说穿了内存管理才是数据库性能的根基。这篇文章我就把KingbaseES也就是金仓数据库的内存管理掰开揉碎讲给你听特别是那些只能手动调的内存参数该怎么设、怎么测、怎么避开坑。前言为什么内存管理这么重要先说个我自己亲身经历的事儿。去年我接手了一个政务系统的KingbaseES数据库业务部门天天投诉说白天高峰期查询特别慢。我登上去一看好家伙shared_buffers才设了128MB。这可是台配了128GB内存的服务器啊我就问之前负责的DBA为什么这么设他说默认值就挺好的没动过。我当时心里就想这不就跟买了辆好车却只挂一档开一样嘛。KingbaseES数据库的内存管理有个特点。它不支持自动内存管理只支持手动配置【turn0search26】。也就是说你不能像用某些数据库那样设个“自动管理”就完事了。都得你自己动手调每个内存区域的大小都得通过配置参数去直接控制【turn0search26】。这种设计吧有好也有坏。好处是你对内存有绝对的控制权想怎么分配就怎么分配。坏处就是你得搞懂每个参数是干嘛的要是不懂还瞎设性能反而会更差。这篇文章我就带你把KingbaseES的内存结构搞明白然后一个参数一个参数地跟你说该怎么设什么场景该调大什么场景该调小。一、KingbaseES内存结构概述要搞明白内存管理首先得知道KingbaseES的内存是怎么分块的。简单来说内存总共分成两大块。分别是系统全局区也就是SGA还有进程全局区也就是PGA【turn0search26】。1.1 系统全局区SGASGA是什么呢它是一组共享的内存结构里面存着一个KingbaseES数据库实例的数据和控制信息【turn0search26】。说白了SGA就是所有数据库进程共用的一块内存区域大家都能往里面放东西也都能从里面拿东西。SGA主要包含三个部分数据页面缓存这是SGA里占比最大的一块存的是最近从数据文件里读取的数据块用来提高数据库的处理性能【turn0search26】。你可以把它理解成数据库的“短期记忆”越常用的数据越放在这里就不用每次都去磁盘上找了。日志页面缓存用来缓存修改数据过程中生成的REDO记录【turn0search26】。这就相当于数据库的“操作日志”先写日志再改数据保证事务的持久性。锁缓存存的是并发控制机制的锁信息【turn0search26】。数据库就像个管交通的得知道谁在访问哪个表避免大家起冲突。1.2 进程全局区PGAPGA是什么呢它是存单个服务进程的数据和控制信息的属于非共享的内存区域【turn0search26】。也就是说每个数据库连接都有自己的PGA别的连接碰不到你的这块内存。PGA主要包含这么几个部分临时页面缓存在进程的私有内存里缓存临时表的数据页面【turn0search26】。工作内存服务器对元组做排序或者连接运算的时候需要在PGA里缓存临时的结果集数据【turn0search26】。要是这块内存不够用的话数据库就得转到磁盘上去生成临时文件。那速度嘛可就慢多了。维护工作内存做维护性操作的时候用的最大内存空间比如VACUUM、建索引、加外键这些操作【turn0search26】。二、为什么KingbaseES只支持手动内存管理这可能是很多人都想问的问题。为什么就不能像某些数据库那样设个“自动内存管理”就完事了呢其实吧这跟KingbaseES的设计思路有关系。金仓数据库是面向企业层级里的关键业务做的主打可控性和可预测性【turn0search31】。自动内存管理听起来挺好但实际用起来有几个问题不可预测性自动管理就意味着数据库自己决定内存怎么分配。今天可能这么分明天可能就那样分了性能表现不稳定。调优困难真出了性能问题你都不知道该调哪里。毕竟内存是数据库在“自动”管着。资源争抢在容器化或者虚拟化的环境里自动内存管理可能会跟宿主机的资源管理策略起冲突。所以KingbaseES选择了手动内存管理把控制权交到DBA手里。当然了这对DBA的要求也就高了。你得懂每个参数的含义才能把数据库调到最好的状态。三、关键内存参数详解下面就是重头戏了。KingbaseES提供了一大堆内存配置参数我挑几个最重要的跟你好好讲讲。3.1 shared_buffers数据页面缓存这个参数可以说是SGA里最核心的直接决定了数据库能缓存多少数据页。作用在共享内存里缓存数据页面减少磁盘的读写次数【turn0search26】。配置建议推荐值操作系统总内存的25%到40%【turn0search26】上限不建议超过操作系统总内存的80%【turn0search26】改完之后得重启数据库才能生效实际经验我一般是这么设的。如果服务器是专门跑数据库的我就设到物理内存的40%左右。比如64GB内存的服务器我会设成24GB左右。如果是和其他应用混部的话那就得看情况了可能只能给到20%。-- 查看当前值SHOWshared_buffers;-- 修改示例在kingbase.conf中设置shared_buffers24GB踩坑经历我有次就把shared_buffers设得太大了直接设了物理内存的60%。结果操作系统留给其他进程的内存不够导致数据库进程直接被OOM Killer杀掉了。所以千万别贪心得给操作系统留点余地。3.2 work_mem工作内存这个参数控制的是单个排序或者哈希操作能使用的内存量。作用服务器做排序或者连接运算的时候用来缓存临时的结果集数据【turn0search26】。要是空间不够的话数据库就会转用临时文件来存这部分数据【turn0search26】。配置建议默认值4MB一般来说都偏小推荐值根据查询的复杂度和并发度调整通常是8MB到64MB注意啊这是每个排序操作单独分配的内存不是总共的实际经验这个参数真不能设太大。因为它是每个排序操作都要单独分配一份的。假设你设了64MB同时有100个排序操作在跑那就是6.4GB的内存需求搞不好直接把内存给吃光了。我的做法是这样的。先看业务高峰期有多少并发查询再估算每个查询平均有几个排序操作最后根据剩下的内存来分配。-- 查看当前值SHOWwork_mem;-- 修改示例ALTERSYSTEMSETwork_mem32MB;案例之前碰到个报表系统白天高峰期特别慢。我查了执行计划发现很多查询都用了外部排序也就是写到临时文件里那种。把work_mem从默认的4MB调到32MB之后这些查询全部变成了内存排序响应时间直接从30秒降到了5秒。3.3 maintenance_work_mem维护工作内存这个参数控制的是维护操作能使用的内存量比如VACUUM、建索引这些操作。作用做维护性操作的时候能用的最大内存空间比如VACUUM、建索引、加外键这些【turn0search26】。设得大一点可以有效提升清理和恢复数据的速度【turn0search26】。配置建议默认值64MB对大数据库来说太小了推荐值512MB到2GB针对大数据库的情况注意啊这块内存只有做维护操作的时候才会用平时不占资源实际经验要是你有大表需要经常做VACUUM或者创建索引这个参数一定要调大。我有次给一个10GB的表建索引maintenance_work_mem只设了64MB结果跑了半小时才完。后来调到2GB5分钟就搞定了。-- 查看当前值SHOWmaintenance_work_mem;-- 修改示例ALTERSYSTEMSETmaintenance_work_mem2GB;3.4 wal_buffers日志缓冲区这个参数控制的是WAL日志的缓冲区大小。作用缓存重做日志的内容再由日志写进程和服务进程刷写到磁盘上【turn0search26】。配置建议默认值-1也就是自动配置是按shared_buffers的1/32来算的但不会小于64KB也不会大于WAL段的尺寸推荐值一般用默认值就行高并发写入的场景可以适当调大一点实际经验这个参数一般不用动除非你的事务修改的数据量特别大。我有次碰到一个高并发写入的场景默认的wal_buffers太小了导致日志写进程频繁刷盘拖了性能的后腿。我调到16MB之后情况就好多了。-- 查看当前值SHOWwal_buffers;-- 修改示例ALTERSYSTEMSETwal_buffers16MB;3.5 temp_buffers临时表缓存这个参数控制的是每个会话为临时表分配的内存量。作用在进程的私有内存里缓存临时表的数据页面【turn0search26】。配置建议默认值8MB推荐值根据临时表的使用情况调整一般不用动实际经验要是你的业务会大量用到临时表比如复杂的报表查询可以适当调大这个值。但要注意这是每个会话都会分配一份的设太大了会浪费内存。-- 查看当前值SHOWtemp_buffers;-- 修改示例ALTERSYSTEMSETtemp_buffers16MB;四、内存配置实践光知道单个参数还不够关键是怎么组合着配置。下面我给你几个典型场景的配置建议。4.1 OLTP高并发小事务场景OLTP场景的特点就是并发高、事务小、查询都比较简单。比如银行转账、电商下单这种。内存配置建议shared_buffers物理内存的30%用来缓存常用的数据页work_mem8到16MB避免每个事务占用太多内存maintenance_work_mem512MB足够支撑日常的维护操作max_connections要设置得合理避免把内存耗尽示例配置以64GB内存的服务器为例# 内存相关配置 shared_buffers 18GB work_mem 12MB maintenance_work_mem 1GB effective_cache_size 48GB # 告诉优化器操作系统有多少内存可用于缓存4.2 OLAP复杂分析查询场景OLAP场景的特点是查询复杂、数据量大、并发比较低。比如数据仓库、报表系统这种。内存配置建议shared_buffers物理内存的40%尽量多缓存数据页work_mem64到256MB复杂查询需要更多的排序内存maintenance_work_mem2到4GB支撑大表的维护操作max_parallel_workers设置得合理一点利用多核来加速示例配置以128GB内存的服务器为例# 内存相关配置 shared_buffers 48GB work_mem 128MB maintenance_work_mem 3GB effective_cache_size 96GB max_parallel_workers 84.3 混合负载场景很多业务既有OLTP又有OLAP这种情况是最头疼的。内存配置建议可以采用折中方案或者用资源队列来控制不同类型的查询也可以考虑用读写分离集群读和写分别配置示例配置以64GB内存的服务器为例# 内存相关配置 shared_buffers 24GB work_mem 32MB maintenance_work_mem 1.5GB effective_cache_size 56GB我的建议碰到这种情况我一般会这么处理。先看看业务的高峰期是什么时候。要是OLTP和OLAP的高峰期错开的比如白天OLTP忙、晚上OLAP跑批那可以用一套配置取个中间值。要是高峰期重叠的话那就得考虑用读写分离集群了让OLTP走主库、OLAP走备库各管各的。还有个办法是用资源队列。把不同的用户或者会话分到不同的队列里给每个队列设不同的内存限制。这样就能防止OLAP查询把内存吃光把OLTP给饿死了。不过说实话混合负载是最考验DBA功力的。我碰到过好多次一开始折中配置结果两边都不满意。最后还是上了读写分离集群才算彻底解决问题。五、内存监控与调优配置完了可不代表就完事了。你得盯着内存的使用情况看看配置合不合理。5.1 查看内存使用情况KingbaseES提供了一些系统视图可以用来查看内存的使用情况-- 查看共享内存使用情况SELECTname,setting,unit,contextFROMsys_settingsWHEREnameIN(shared_buffers,wal_buffers,work_mem,maintenance_work_mem);-- 查看缓冲区命中率SELECTsum(heap_blks_read)asheap_read,sum(heap_blks_hit)asheap_hit,sum(heap_blks_hit)/(sum(heap_blks_hit)sum(heap_blks_read))ascache_hit_ratioFROMsys_statio_user_tables;怎么解读结果呢缓存命中率最好保持在99%以上。要是低于95%就说明shared_buffers可能不够用了如果heap_read的数值很大说明很多数据不在内存里得从磁盘读取5.2 监控操作系统内存数据库的内存配置不能孤立着看还得看操作系统层面的内存使用情况# 查看内存使用情况free-h# 查看进程内存使用top-o%MEM重点关注这几项available内存也就是操作系统还有多少内存能用swap使用情况要是开始用swap了说明物理内存不够用了数据库进程的内存占用有没有超过配置的数值5.3 常见内存问题与解决碰到内存问题的时候我一般会先看看是什么类型的。下面给你说几种常见的。问题一缓存命中率低这个问题的现象很直接cache_hit_ratio低于95%了。那为什么会出现这种情况呢通常来说有两个原因。一个是shared_buffers设得太小缓存装不下常用数据。另一个是工作集本来就超过了内存容量也就是说你的业务需要频繁访问的数据总量比物理内存还大。怎么解决呢我的思路是这样的。先试着增加shared_buffers的大小但不能太贪心不能超过物理内存的40%。要是加了还是不行那可能就是查询本身的问题得优化查询语句减少全表扫描这种操作。实在不行的话就考虑加物理内存吧。问题二内存不足导致OOM这个问题更严重数据库进程直接被系统杀掉了日志里能看到Out of memory的错误。碰到OOM基本就是内存配置超了。可能的情况有两种。一种是shared_buffers加上work_mem乘以并发数加起来超过了物理内存。另一种是maintenance_work_mem在执行大维护操作的时候一下子把内存吃光了。解决方法其实也简单。要么调小shared_buffers要么降低work_mem或者减少并发连接数。要是维护操作经常出问题就调小maintenance_work_mem。要是都不行那就得加物理内存了。我有次碰到一个客户白天没事一到晚上跑批就OOM。查了半天发现是夜间有个大VACUUM操作maintenance_work_mem设得太大了。调小之后就好了。问题三临时文件使用过多这个问题的现象是sys_temp目录下生成了大量文件。原因嘛通常就是work_mem太小。排序和哈希操作内存不够用只能往磁盘上写临时文件。磁盘IO一多性能自然就下来了。解决方法有两个方向。一个是增加work_mem的大小让操作尽量在内存里完成。另一个是从查询本身下手优化SQL减少不必要的排序操作。六、内存调优案例给你讲个我实际处理过的案例让你看看内存调优具体是怎么做的。6.1 案例背景有个电商系统用的是KingbaseES数据库服务器配了64GB内存。一到业务高峰期也就是晚上8点到10点数据库响应就特别慢。CPU使用率不高但IO等待特别高。6.2 问题诊断我登上去看了下配置当时就愣了shared_buffers 128MB work_mem 4MB maintenance_work_mem 64MB effective_cache_size 4GB我的天这配置也太保守了吧。64GB内存的服务器shared_buffers才128MB这能用得顺畅才怪。再查了下缓存命中率SELECTsum(heap_blks_read)asheap_read,sum(heap_blks_hit)asheap_hit,sum(heap_blks_hit)/(sum(heap_blks_hit)sum(heap_blks_read))ascache_hit_ratioFROMsys_statio_user_tables;结果只有78%。也就是说有22%的数据请求都得从磁盘读取。这个78%是什么概念呢打个比方你每查100次数据有22次都得去磁盘上找。磁盘可比内存慢多了这就是为什么IO等待特别高的原因。6.3 调优过程第一步先调整shared_buffers。我把shared_buffers调到了16GB也就是物理内存的25%shared_buffers 16GB重启数据库之后缓存命中率提升到了96%。但还有提升的空间。第二步调整work_mem。业务高峰期的并发连接数大概在200左右大部分都是简单查询只有少数复杂的报表查询。我把work_mem调到了16MBwork_mem 16MB这样一来复杂查询有足够的排序内存简单查询也不会浪费太多资源。第三步调整maintenance_work_mem。系统夜间有VACUUM的作业我把maintenance_work_mem调到了2GBmaintenance_work_mem 2GB第四步调整effective_cache_size。这个参数是告诉优化器操作系统有多少内存可以用来缓存数据。我设成了48GBeffective_cache_size 48GB6.4 调优效果调优之后同样的业务高峰期缓存命中率从78%提升到了99.5%平均响应时间从200ms降到了80msIO等待从30%降到了5%业务部门再也不投诉了我也终于能睡个好觉了。七、总结本文深入解析KingbaseES数据库内存管理的核心机制强调其手动配置特性对性能的关键影响。重点剖析shared_buffers、work_mem、maintenance_work_mem等核心参数的配置原则与实战经验结合OLTP与OLAP场景给出优化建议揭示合理内存分配对提升数据库响应速度、避免资源争抢的重要性助力DBA精准调优实现性能最大化。
返回列表