内存和负载管理

内存和负载管理

Greenplum数据库集群中,内存管理对性能有显著的影响。默认设置适合于大部分环境。不要更改默认设置,除非理解系统上的内存特点和使用。

解决内存不足错误

内存不足错误消息表明Greenplum的Segment、主机和进程遇到了内存不足错误。例如:
Out of memory (seg27 host.example.com pid=47093)
VM Protect failed to allocate 4096 bytes, 0 MB available
Greenplum数据库中一些常见的导致内存不足的情况是:
  • 集群上可用的系统内存(RAM)不足
  • 内存参数配置不当
  • Segment级别有数据倾斜
  • 查询级别有操作性倾斜

下面是内存不足情况的可能解决方案:

  • 调优查询以要求较少的内存
  • 使用资源队列降低查询并发
  • 降低Greenplum集群中每台主机上的Segment数量
  • 增加主机上的内存
  • 在数据库级别上验证gp_vmem_protect_limit配置参数。最大安全设置的计算请见为Greenplum数据库配置内存
  • 使用会话设置来降低特定查询使用的statement_mem
  • 在数据库级别降低statement_mem
  • 在资源队列上设置内存限额以限制资源队列中执行的查询所使用的内存

向集群中增加Segment主机本身不会缓解内存不足问题。每个查询使用的内存由statement_mem参数决定,并且在查询被调用时会设置它。不过,如果增加更多的主机允许每台主机上的Segment数量降低,那么gp_vmem_protect_limit中分配的内存量就可以上升。

为Greenplum数据库配置内存

如果周到地管理内存,大部分内存不足的情况是可以避免的。

并不总是可以增加系统内存,但是用户可以通过正确地配置内存使用和设置资源队列管理预期负载来防止内存不足的情况。

有必要考虑由于失效导致镜像Segment变成主Segment的内存需求,以确保在主Segment或者Segment主机失效时集群能够继续运转。

下面是推荐的操作系统以及Greenplum数据库内存设置:

  • 不要配置OS使用巨型页。
  • vm.overcommit_memory

    这是一个Linux内核参数,在/etc/sysctl.conf中设置。它应该总是被设置为2。它决定OS判断可以给进程分配多少内存时使用的方法,2是对于Greenplum数据库唯一安全的设置。

  • vm.overcommit_ratio

    这是一个Linux内核参数,在/etc/sysctl.conf中设置。它是可以用于应用进程的RAM的百分数。剩余的保留给操作系统。Red Hat上默认为50。

    vm.overcommit_ratio设置得太高可能会导致没有为操作系统保留足够的内存,进而导致Segment主机失效或者数据库失效。将这个值设置得太低会降低并发量和通过降低Greenplum数据库可用内存量能运行的查询复杂度。在增加这一设置时,有必要记住总是为操作系统活动保留一些内存。

    vm.overcommit_ratio计算值的方法请见Segment内存配置

  • gp_vmem_protect_limit

    使用gp_vmem_protect_limit设置实例能够为在每个Segment数据库中完成的所有工作分配的最大内存。不要把这个值设置得高于系统上的物理RAM。如果gp_vmem_protect_limit太高,有可能耗尽系统上的内存并且正常的操作可能会失败,导致Segment失效。如果gp_vmem_protect_limit被设置为一个安全的较低值,系统上真正的内存耗尽就能避免。查询可能会因为达到限制而失败,但是系统崩溃和Segment失效可以避免,这也是我们想要的行为。

    gp_vmem_protect_limit计算安全值的方法请见Segment内存配置

  • runaway_detector_activation_percent

    失控查询终止在Greenplum数据库4.3.4中被引入,它能防止内存不足的问题。runaway_detector_activation_percent系统参数控制触发查询终止的gp_vmem_protect_limit内存利用率。默认它被设置为90%。如果一个Segment利用的gp_vmem_protect_limit memory内存的百分比超过指定的值,Greenplum数据库会基于内存使用终止查询,从消耗内存量最大的查询开始。查询会被挨个终止直至 gp_vmem_protect_limit的利用率重新低于指定的百分比。

  • statement_mem
    使用statement_mem分配每个Segment数据库中一个查询所使用的内存。如果要求额外的内存,将会溢出到磁盘。按照下面的额方式为statement_mem设置最优值:
    (vmprotect * .9) / max_expected_concurrent_queries

    statement_mem的默认值是125MB。例如,一个使用默认statement_mem值运行在Dell EMC DCA V2系统上的查询将在每台Segment服务器上使用1GB内存(8个Segment ⨉ 125MB)。为要求额外内存完成的特定查询在会话级别上设置statement_mem。在并发性低的集群上这种设置可以很好地管理查询内存。对于高并发的集群还是要使用资源队列来控制在系统上运行什么以及运行多少。

  • gp_workfile_limit_files_per_query

    设置gp_workfile_limit_files_per_query以限制每个查询允许使用的临时溢出文件(工作文件)的最大数量。当查询要求的内存比它能分配的更多时,它将创建溢出文件。当上述限制被超过时,查询会被中止。默认值为零,允许无限多的溢出文件并且可能会填满文件系统。

  • gp_workfile_compress_algorithm

    如果有很多溢出文件,则设置gp_workfile_compress_algorithm为压缩这些溢出文件。压缩溢出文件可能有助于避免IO操作导致磁盘子系统过载。

内存配置计算实例

  • 总RAM = 256GB
  • SWAP = 64GB
  • 一个块中有4台主机,每台主机上8个主Segment和8个镜像Segment
  • 失效期间每台主机上的主Segment最大数目是11
vm.overcommit_ratio calculation
gp_vmem = ((SWAP + RAM) – (7.5GB + 0.05 * RAM)) / 1.7
        = ((64 + 256) - (7.5 + 0.05 * 256)) / 1.7 
        = 176

vm.overcommit_ratio = (RAM - (0.026 * gp_vmem)) / RAM 
                    = (256 - (0.026 * 176)) / 256 
                    = .982
vm.overcommit_ratio设置为98。
gp_vmem_protect_limit calculation
gp_vmem_protect_limit = gp_vmem / maximum_acting_primary_segments
                      = 176 / 11 
                      = 16GB
                      = 16384MB

配置资源队列

Greenplum数据库的资源队列为管理集群负载提供了一种强有力的机制。队列可以被用来限制活动查询的数量以及队列中查询可使用的内存量。当查询被提交给Greenplum数据库时,它会被加入一个资源队列,资源队列会决定该查询是否应该被接受并且何时有资源可用来执行它。

  • 不要使用默认队列。把所有角色关联到一个用户定义的资源队列。

    每个登录用户(角色)都被关联到单个资源队列,任何该用户提交的查询都由关联的资源队列处理。如果没有为用户的查询明确地分派一个队列,则会由默认队列pg_default处理之。

  • 不要用gpadmin角色或者其他超级用户角色运行查询。

    超级用户会被从资源队列限制中排除,因此超级用户的查询运行不会考虑在其所属队列上设置的限制。

  • 使用ACTIVE_STATEMENTS资源队列参数来限制特定队列成员能够并发运行的活动查询数量。

  • 使用MEMORY_LIMIT参数控制通过队列运行的查询可以利用的内存总量。通过组合ACTIVE_STATEMENTSMEMORY_LIMIT属性,管理员可以完全控制从一个给定资源队列发出的活动。

    分配按如下方式进行:假定资源队列sample_queueACTIVE_STATEMENTS被设置为10,而MEMORY_LIMIT被设置为2000MB。这限制该队列在每个Segment上使用大约2GB内存。对于每台服务器有8个Segment的集群,sample_queue在每台服务器上的总用量是16GB(2GB * 8 Segment/服务器)。如果Segment服务器有64GB内存,系统中可以有不超过四个这种资源队列,再多就会内存不足(4队列 * 16GB/队列)。

    注意通过使用STATEMENT_MEM,运行在队列中的个体查询能够分配超过其内存“份额”的内存,从而降低队列中其他查询可用的内存。

  • 资源队列优先级可以被用来排列具有预期结果的负载。带有MAX优先权的队列会扼杀所有其他队列中的活动,直至MAX队列完成所有查询的运行。

  • 根据负载和现状动态修改资源队列以匹配队列的实际需求。

    典型的环境中有基于当前情况和系统适用类型而改变的操作流程。用户可以把这些更改写成脚本并且增加crontab项来执行这些脚本。

  • 使用gptoolkit查看资源队列使用以及理解队列如何工作。