本文介绍如何使用云数据库ClickHouse的资源队列增强功能。

背景信息

ClickHouse官方开源版目前没有资源队列的功能设计,以下资源队列相关功能是云数据库ClickHouse的增强功能,并且只适配于v20.3以及更高的内核版本。由于ClickHouse官方开源版有一套完整的用户级别内存隔离机制存在,资源队列功能在新购库中默认不开启,需要使用资源队列功能的用户可通过提交工单自助开启。

资源队列定义

创建资源队列语法:

-- 创建资源队列定义
CREATE RESOURCE QUEUE [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster]
  * {[SET] MEMORY = {number}
  * [, CONCURRENCY = {number}]
  * [, PRIORITY = { LOWEST | LOW | NORMAL | HIGH | HIGHEST }]
  * [, ISOLATE = {number}]
    * }
  * [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]

-- 更改指定资源队列定义
ALTER RESOURCE QUEUE [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster]
  * {[SET] MEMORY = {number}
  * [, CONCURRENCY = {number}]
  * [, PRIORITY = { LOWEST | LOW | NORMAL | HIGH | HIGHEST }]
  * [, ISOLATE = {number}]
    * }
  * [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]  

-- 查看指定资源队列定义
SHOW CREATE resource queue name

-- 查看当前用户使用的资源队列定义
SHOW CREATE resource queue current

-- 删除指定资源队列定义
DROP resource queue if exists name
定义参数说明:
  • memory:声明创建的资源队列内存池大小,如果节点的总内存被已有的资源队列分配完,则创建会失败。
  • concurency:声明创建的资源队列中查询的并发数限制,默认值为20,并发限制会对用户发起的查询进行阻塞排队,对系统发起的子查询不会阻塞但是会计入到当前并发统计中。即并发限制为20的资源队列当前同时在跑的系统子查询可以达到25个,但此时用户发起的查询全部会被阻塞,直到系统子查询数降低到20以下。
  • priority:声明创建的资源队列优先级,包含cpu调度优先级和内存抢占优先级。
  • isolate:声明创建的资源队列内存隔离级别。
    • 默认值是0,表示没有隔离,当目标资源队列中的内存使用率处于低水位时,更高优先级的资源队列在内存不够用时可以临时抢占目标资源队列的内存。
    • 设定为1时,表示该资源队列有软隔离,不可被高优先级队列抢占内存。
    • 设定为2时,表示该资源队列绝对隔离,不可被抢占内存,同时也不会去抢占低优先级队列的内存。
  • role:通过To role [,...]声明,把目标资源队列绑定到多个用户上,对应用户的查询默认会进入到目标资源队列中。当同时有多个资源队列绑定同一用户时,系统会随机选择一个最高优先级的资源队列执行查询。
配置参数说明:
  • target_resource_queue:声明目标查询强制路由到指定资源队列中,也可以在用户的profile文件中配置强制用户对应的查询强制路由。
  • resource_queue_max_wait_ms:声明查询在资源队列中因为并发限制阻塞排队的最长等待时间,默认10s。

示例:

CREATE RESOURCE QUEUE IF NOT EXISTS test_queue ON CLUSTER cluster SET 
  MEMORY = 1073741824, CONCURRENCY = 20, ISOLATE = 0, PRIORITY = NORMAL 
    TO default;

CREATE RESOURCE QUEUE IF NOT EXISTS anonymous_queue ON CLUSTER cluster SET 
  MEMORY = 1073741824, CONCURRENCY = 20, ISOLATE = 1, PRIORITY = LOW;

SHOW CREATE resource queue test_queue;

SHOW CREATE resource queue current;

SELECT count (distinct intDiv(number, 10)) FROM numbers(100000) settings target_resource_queue='anonymous_queue';

DROP resource queue if exists test_queue;

DROP resource queue if exists anonymous_queue;

资源队列状态查询

List当前所有的资源队列定义:
show resource queues;

返回结果说明:

名称 类型 说明
name String 资源队列名。
concurrency UInt32 资源队列的并发限制。
memory UInt64 资源队列的内存池大小。
isolate UInt8 资源队列的隔离级别。
priority Enum8(枚举) 资源队列的优先级别。
roles Array<String> 资源队列绑定的所有相关用户。
List指定资源队列的查询使用状态:
show resource queue stat [CURRENT | ALL];

返回结果说明:

名称 类型 说明
name String 资源队列名。
running_query UInt32 资源队列中正在执行的查询数量。
waiting_query UInt32 资源队列中正在等待执行的查询数量。
grabbing_query UInt32 正在临时抢占使用资源队列内存池的查询(不属于该资源队列)数量。
allocated_memory UInt64 资源队列内存池被正常申请使用的内存大小。
grabbed_memory UInt64 资源队列内存池被临时抢占使用的内存大小。
free_memory UInt64 资源队列内存池当前剩余内存大小。

资源队列相关查询异常

并发限制导致查询超时
相关错误码:13005
解决方案:降低客户端的查询并发数。
Bad Query使用内存超过资源队列内存池
相关错误码:241
解决方案:优化查询Plan,或调大资源队列内存池。
查询强制路由的资源队列不存在
相关错误码:13006
解决方案:检查资源队列创建状态。
查询临时抢占申请低优先级资源队列被Kill
相关错误码:394
解决方案:降低资源队列并发数,调整队列优先级。