工作负载调度
当 ClickHouse 同时执行多个查询时,它们可能正在使用共享资源(例如磁盘)。可以应用调度约束和策略来规范资源如何在不同工作负载之间被利用和共享。对于每个资源,都可以配置调度层次结构。层次结构根表示一个资源,而叶节点是队列,用于保存超出资源容量的请求。
目前,只有远程磁盘 IO 可以使用描述的方法进行调度。对于 CPU 调度,请参阅关于线程池和 concurrent_threads_soft_limit_num
的设置。对于灵活的内存限制,请参阅 内存过载
磁盘配置
要为特定磁盘启用 IO 调度,您必须在存储配置中指定 read_resource
和/或 write_resource
。它告诉 ClickHouse 应该为给定磁盘的每个读取和写入请求使用哪个资源。读取和写入资源可以引用相同的资源名称,这对于本地 SSD 或 HDD 很有用。多个不同的磁盘也可以引用相同的资源,这对于远程磁盘很有用:如果您希望能够在例如“生产”和“开发”工作负载之间公平分配网络带宽。
示例
<clickhouse>
<storage_configuration>
...
<disks>
<s3>
<type>s3</type>
<endpoint>https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/root-path/</endpoint>
<access_key_id>your_access_key_id</access_key_id>
<secret_access_key>your_secret_access_key</secret_access_key>
<read_resource>network_read</read_resource>
<write_resource>network_write</write_resource>
</s3>
</disks>
<policies>
<s3_main>
<volumes>
<main>
<disk>s3</disk>
</main>
</volumes>
</s3_main>
</policies>
</storage_configuration>
</clickhouse>
另一种表达资源使用的磁盘的方式是 SQL 语法
CREATE RESOURCE resource_name (WRITE DISK disk1, READ DISK disk2)
资源可以用于任意数量的磁盘进行读取或写入,或者同时用于读取和写入。有一种语法允许将资源用于所有磁盘
CREATE RESOURCE all_io (READ ANY DISK, WRITE ANY DISK);
请注意,服务器配置选项优先于 SQL 定义资源的方式。
工作负载标记
可以使用设置 workload
标记查询以区分不同的工作负载。如果未设置 workload
,则使用值“default”。请注意,您可以使用设置配置文件来指定其他值。如果希望来自用户的所有查询都用固定的 workload
设置值标记,则可以使用设置约束使 workload
保持不变。
可以为后台活动分配 workload
设置。合并和突变分别使用 merge_workload
和 mutation_workload
服务器设置。这些值也可以使用 merge_workload
和 mutation_workload
MergeTree 设置为特定表覆盖
让我们考虑一个具有两个不同工作负载的系统示例:“生产”和“开发”。
SELECT count() FROM my_table WHERE value = 42 SETTINGS workload = 'production'
SELECT count() FROM my_table WHERE value = 13 SETTINGS workload = 'development'
资源调度层次结构
从调度子系统的角度来看,资源表示调度节点的层次结构。
可能的节点类型
inflight_limit
(约束)- 如果并发进行中的请求数超过max_requests
,或者它们的总成本超过max_cost
,则阻止;必须有一个子节点。bandwidth_limit
(约束)- 如果当前带宽超过max_speed
(0 表示无限制)或突发超过max_burst
(默认等于max_speed
),则阻止;必须有一个子节点。fair
(策略)- 根据最大-最小公平性,从其子节点之一中选择要服务的下一个请求;子节点可以指定weight
(默认为 1)。priority
(策略)- 根据静态优先级(值越低表示优先级越高),从其子节点之一中选择要服务的下一个请求;子节点可以指定priority
(默认为 0)。fifo
(队列)- 层次结构的叶节点,能够保存超出资源容量的请求。
为了能够使用底层资源的全部容量,您应该使用 inflight_limit
。请注意,较低的 max_requests
或 max_cost
数量可能导致资源利用率不足,而过高的数量可能导致调度程序内部出现空队列,这反过来会导致子树中策略被忽略(不公平或忽略优先级)。另一方面,如果您想保护资源免受过高利用率的影响,则应使用 bandwidth_limit
。当在 duration
秒内消耗的资源量超过 max_burst + max_speed * duration
字节时,它会进行节流。同一资源上的两个 bandwidth_limit
节点可用于限制短时间间隔内的峰值带宽和长时间间隔内的平均带宽。
以下示例显示了如何定义图中所示的 IO 调度层次结构
<clickhouse>
<resources>
<network_read>
<node path="/">
<type>inflight_limit</type>
<max_requests>100</max_requests>
</node>
<node path="/fair">
<type>fair</type>
</node>
<node path="/fair/prod">
<type>fifo</type>
<weight>3</weight>
</node>
<node path="/fair/dev">
<type>fifo</type>
</node>
</network_read>
<network_write>
<node path="/">
<type>inflight_limit</type>
<max_requests>100</max_requests>
</node>
<node path="/fair">
<type>fair</type>
</node>
<node path="/fair/prod">
<type>fifo</type>
<weight>3</weight>
</node>
<node path="/fair/dev">
<type>fifo</type>
</node>
</network_write>
</resources>
</clickhouse>
工作负载分类器
工作负载分类器用于定义从查询指定的 workload
到应为特定资源使用的叶队列的映射。目前,工作负载分类很简单:仅提供静态映射。
示例
<clickhouse>
<workload_classifiers>
<production>
<network_read>/fair/prod</network_read>
<network_write>/fair/prod</network_write>
</production>
<development>
<network_read>/fair/dev</network_read>
<network_write>/fair/dev</network_write>
</development>
<default>
<network_read>/fair/dev</network_read>
<network_write>/fair/dev</network_write>
</default>
</workload_classifiers>
</clickhouse>
工作负载层次结构(仅限 SQL)
在 XML 中定义资源和分类器可能具有挑战性。ClickHouse 提供了更方便的 SQL 语法。使用 CREATE RESOURCE
创建的所有资源都共享相同的层次结构,但在某些方面可能有所不同。使用 CREATE WORKLOAD
创建的每个工作负载都为每个资源维护一些自动创建的调度节点。子工作负载可以在另一个父工作负载内部创建。以下示例定义了与上述 XML 配置完全相同的层次结构
CREATE RESOURCE network_write (WRITE DISK s3)
CREATE RESOURCE network_read (READ DISK s3)
CREATE WORKLOAD all SETTINGS max_requests = 100
CREATE WORKLOAD development IN all
CREATE WORKLOAD production IN all SETTINGS weight = 3
没有子节点的叶工作负载的名称可以在查询设置 SETTINGS workload = 'name'
中使用。请注意,使用 SQL 语法时也会自动创建工作负载分类器。
要自定义工作负载,可以使用以下设置
priority
- 兄弟工作负载根据静态优先级值进行服务(值越低表示优先级越高)。weight
- 具有相同静态优先级的兄弟工作负载根据权重共享资源。max_requests
- 此工作负载中并发资源请求数的限制。max_cost
- 此工作负载中并发资源请求的总进行中字节数计数的限制。max_speed
- 此工作负载的字节处理速率限制(每个资源的限制是独立的)。max_burst
- 工作负载可以处理的最大字节数,而不会被限制(对于每个资源都是独立的)。
请注意,工作负载设置被转换为一组适当的调度节点。有关更多详细信息,请参阅调度节点类型和选项的描述。
无法为不同的资源指定不同的工作负载层次结构。但是,有一种方法可以为特定资源指定不同的工作负载设置值
CREATE OR REPLACE WORKLOAD all SETTINGS max_requests = 100, max_speed = 1000000 FOR network_read, max_speed = 2000000 FOR network_write
另请注意,如果工作负载或资源被另一个工作负载引用,则无法删除它。要更新工作负载的定义,请使用 CREATE OR REPLACE WORKLOAD
查询。
工作负载和资源存储
所有工作负载和资源的定义(以 CREATE WORKLOAD
和 CREATE RESOURCE
查询的形式)都持久存储在磁盘上的 workload_path
或 ZooKeeper 上的 workload_zookeeper_path
中。建议使用 ZooKeeper 存储以实现节点之间的一致性。或者,可以将 ON CLUSTER
子句与磁盘存储一起使用。
另请参阅
- system.scheduler
- system.workloads
- system.resources
- merge_workload MergeTree 设置
- merge_workload 全局服务器设置
- mutation_workload MergeTree 设置
- mutation_workload 全局服务器设置
- workload_path 全局服务器设置
- workload_zookeeper_path 全局服务器设置