Adhoc类查询通常输入的SQL不确定,使用的内存资源也不确定,因此存在少数查询占用很大内存的风险。 可以对这类负载可以划分到独立的分组,通过Workload Group对内存的硬限的功能,避免突发性的大查询占满所有内存,导致其他查询没有可用内存或者OOM。 当这个Workload Group的内存使用超过配置的硬限值时,会通过杀死查询的方式释放内存,避免进程内存被打满。

测试内存硬限

测试环境

1FE,1BE,BE配置为96核,内存大小为375G。

测试数据集为clickbench,测试方法为使用jmeter起三并发执行q29。

测试不开启Workload Group的内存硬限

  1. 查看进程使用内存。ps命令输出第四列代表进程使用的物理内存的用量,单位为kb,可以看到当前测试负载下,进程的内存使用为7.7G左右。
  1. [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481
  2. 1407481 doris_be 2.0 7896792
  3. [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481
  4. 1407481 doris_be 2.0 7929692
  5. [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481
  6. 1407481 doris_be 2.0 8101232
  1. 使用Doris系统表查看当前Workload Group的内存用量,Workload Group的内存用量为5.8G左右。
  1. mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201;
  2. +-------------------+
  3. | wg_mem_used_mb |
  4. +-------------------+
  5. | 5797.524360656738 |
  6. +-------------------+
  7. 1 row in set (0.01 sec)
  8. mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201;
  9. +-------------------+
  10. | wg_mem_used_mb |
  11. +-------------------+
  12. | 5840.246627807617 |
  13. +-------------------+
  14. 1 row in set (0.02 sec)
  15. mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201;
  16. +-------------------+
  17. | wg_mem_used_mb |
  18. +-------------------+
  19. | 5878.394917488098 |
  20. +-------------------+
  21. 1 row in set (0.02 sec)

这里可以看到进程的内存使用通常要远大于一个Workload Group的内存用量,即使进程内只有一个Workload Group在跑,这是因为Workload Group只统计了查询和部分导入的内存,进程内的其他组件比如元数据,各种Cache的内存是不计算Workload Group内的,也不由Workload Group管理。

测试开启Workload Group的内存硬限

  1. 执行SQL命令修改内存配置。
  1. alter workload group g2 properties('memory_limit'='0.5%');
  2. alter workload group g2 properties('enable_memory_overcommit'='false');
  1. 执行同样的测试,查看系统表的内存用量,内存用量为1.5G左右。
  1. mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201;
  2. +--------------------+
  3. | wg_mem_used_mb |
  4. +--------------------+
  5. | 1575.3877239227295 |
  6. +--------------------+
  7. 1 row in set (0.02 sec)
  8. mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201;
  9. +------------------+
  10. | wg_mem_used_mb |
  11. +------------------+
  12. | 1668.77405834198 |
  13. +------------------+
  14. 1 row in set (0.01 sec)
  15. mysql [information_schema]>select MEMORY_USAGE_BYTES / 1024/ 1024 as wg_mem_used_mb from workload_group_resource_usage where workload_group_id=11201;
  16. +--------------------+
  17. | wg_mem_used_mb |
  18. +--------------------+
  19. | 499.96760272979736 |
  20. +--------------------+
  21. 1 row in set (0.01 sec)
  1. 使用ps命令查看进程的内存用量,内存用量为3.8G左右。
  1. [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481
  2. 1407481 doris_be 1.0 4071364
  3. [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481
  4. 1407481 doris_be 1.0 4059012
  5. [ ~]$ ps -eo pid,comm,%mem,rss | grep 1407481
  6. 1407481 doris_be 1.0 4057068
  1. 同时客户端会观察到大量由于内存不足导致的查询失败。
  1. 1724074250162,14126,1c_sql,HY000 1105,"java.sql.SQLException: errCode = 2, detailMessage = (127.0.0.1)[MEM_LIMIT_EXCEEDED]GC wg for hard limit, wg id:11201, name:g2, used:1.71 GB, limit:1.69 GB, backend:10.16.10.8. cancel top memory used tracker <Query#Id=4a0689936c444ac8-a0d01a50b944f6e7> consumption 1.71 GB. details:process memory used 3.01 GB exceed soft limit 304.41 GB or sys available memory 101.16 GB less than warning water mark 12.80 GB., Execute again after enough memory, details see be.INFO.",并发 1-3,text,false,,444,0,3,3,null,0,0,0

这个报错信息中可以看到,Workload Group使用了1.7G的内存,但是Workload Group的限制是1.69G,这里的计算方式是这样的1.69G = 物理机内存(375) mem_limit(be.conf中的值,默认为0.9) 0.5%(Workload Group的配置) 也就是说,Workload Group中配置的内存百分比是基于Doris进程可用内存再次进行计算的。

使用建议

如上文测试,硬限可以控制Workload Group的内存使用,但却是通过杀死查询的方式释放内存,这对用户来说体验会非常不友好,极端情况下可能会导致所有查询都失败。 因此在生产环境中推荐内存硬限配合查询排队的功能一起使用,可以在限制内存使用的同时保证查询的成功率。