查询复杂度限制
查询复杂度限制是设置的一部分。它们用于提供来自用户界面的更安全执行。几乎所有限制仅适用于 SELECT
。对于分布式查询处理,限制分别应用于每个服务器。
ClickHouse 检查数据部分的限制,而不是检查每一行的限制。这意味着您可以使用数据部分的大小超过限制的值。
对“某事物的最大数量”的限制可以取值为 0,这意味着“无限制”。大多数限制也有一个‘overflow_mode’ 设置,表示当超过限制时该怎么做。它可以取两个值之一:throw
或 break
。聚合限制 (group_by_overflow_mode) 也有值 any
。
throw
– 抛出异常(默认)。
break
– 停止执行查询并返回部分结果,就像源数据用完一样。
any (仅用于 group_by_overflow_mode)
– 继续对已进入集合的键进行聚合,但不将新键添加到集合中。
max_memory_usage
在单个服务器上运行查询时使用的最大 RAM 量。
默认设置为无限制(设置为 0
)。
云默认值:取决于副本上的 RAM 量。
该设置不考虑可用内存量或机器上的总内存量。该限制适用于单个服务器内的一个查询。您可以使用 SHOW PROCESSLIST
来查看每个查询的当前内存消耗量。此外,每个查询的峰值内存消耗量都会被跟踪并写入日志。
不监控某些聚合函数状态的内存使用情况。
不完全跟踪来自 String
和 Array
参数的聚合函数 min
、max
、any
、anyLast
、argMin
、argMax
状态的内存使用情况。
内存消耗也受参数 max_memory_usage_for_user
和 max_server_memory_usage 的限制。
max_memory_usage_for_user
在单个服务器上运行用户查询时使用的最大 RAM 量。
默认值在 Settings.h 中定义。默认情况下,数量不受限制 (max_memory_usage_for_user = 0
)。
另请参阅 max_memory_usage 的描述。
例如,如果要将名为 clickhouse_read
的用户的 max_memory_usage_for_user
设置为 1000 字节,可以使用以下语句
ALTER USER clickhouse_read SETTINGS max_memory_usage_for_user = 1000;
您可以通过注销客户端,重新登录,然后使用 getSetting
函数来验证它是否已生效
SELECT getSetting('max_memory_usage_for_user');
max_rows_to_read
以下限制可以在每个块(而不是每行)上进行检查。也就是说,限制可能会略微被打破。
运行查询时可以从表中读取的最大行数。
max_bytes_to_read
运行查询时可以从表中读取的最大字节数(未压缩数据)。
read_overflow_mode
读取的数据量超过其中一个限制时该怎么做:‘throw’ 或 ‘break’。默认情况下为 throw。
max_rows_to_read_leaf
以下限制可以在每个块(而不是每行)上进行检查。也就是说,限制可能会略微被打破。
运行分布式查询时可以从叶节点上的本地表中读取的最大行数。虽然分布式查询可以向每个分片(叶节点)发出多个子查询,但此限制仅在叶节点上的读取阶段进行检查,并在根节点上的结果合并阶段被忽略。例如,集群由 2 个分片组成,每个分片包含一个包含 100 行的表。然后,假设要从两个表中读取所有数据的分布式查询将使用设置 max_rows_to_read=150
失败,因为总共将是 200 行。而使用 max_rows_to_read_leaf=150
的查询将成功,因为叶节点最多将读取 100 行。
max_bytes_to_read_leaf
运行分布式查询时可以从叶节点上的本地表中读取的最大字节数(未压缩数据)。虽然分布式查询可以向每个分片(叶节点)发出多个子查询,但此限制仅在叶节点上的读取阶段进行检查,并在根节点上的结果合并阶段被忽略。例如,集群由 2 个分片组成,每个分片包含一个包含 100 字节数据的表。然后,假设要从两个表中读取所有数据的分布式查询将使用设置 max_bytes_to_read=150
失败,因为总共将是 200 字节。而使用 max_bytes_to_read_leaf=150
的查询将成功,因为叶节点最多将读取 100 字节。
read_overflow_mode_leaf
读取的数据量超过其中一个叶节点限制时该怎么做:‘throw’ 或 ‘break’。默认情况下为 throw。
max_rows_to_group_by
从聚合接收到的唯一键的最大数量。此设置允许您在聚合时限制内存消耗。
group_by_overflow_mode
当聚合的唯一键数量超过限制时该怎么做:‘throw’、‘break’ 或 ‘any’。默认情况下为 throw。使用 ‘any’ 值可以让您运行 GROUP BY
的近似值。此近似值的质量取决于数据的统计性质。
max_bytes_before_external_group_by
启用或禁用在外部内存中执行 GROUP BY
子句。请参阅 外部内存中的 GROUP BY。
可能的值
- 单个 GROUP BY 操作可以使用 RAM 的最大量(以字节为单位)。
- 0 — 在外部内存中禁用
GROUP BY
。
默认值:0
。
云默认值:每个副本的内存量的一半。
max_bytes_before_external_sort
启用或禁用在外部内存中执行 ORDER BY
子句。请参阅 ORDER BY 实现细节
- 单个 ORDER BY 操作可以使用 RAM 的最大量(以字节为单位)。推荐值是可用系统内存的一半。
- 0 — 在外部内存中禁用
ORDER BY
。
默认值:0。
云默认值:每个副本的内存量的一半。
max_rows_to_sort
排序前最大行数。这使您可以在排序时限制内存消耗。
max_bytes_to_sort
排序前最大字节数。
sort_overflow_mode
如果在排序前收到的行数超过任何一个限制,该怎么做:‘throw’ 或 ‘break’。默认情况下,为 ‘throw’。
max_result_rows
结果中行数的限制。也适用于子查询,以及在运行分布式查询的一部分时在远程服务器上。当值为 0
时,不应用任何限制。
默认值:0
。
云默认值:0
。
max_result_bytes
结果中字节数的限制。与之前的设置相同。
result_overflow_mode
如果结果的大小超过任何一个限制,该怎么做:‘throw’ 或 ‘break’。
使用 ‘break’ 类似于使用 LIMIT。Break
仅在块级别中断执行。这意味着返回的行数大于 max_result_rows,是 max_block_size 的倍数,并且取决于 max_threads。
默认值:throw
。
云默认值:throw
。
示例
SET max_threads = 3, max_block_size = 3333;
SET max_result_rows = 3334, result_overflow_mode = 'break';
SELECT *
FROM numbers_mt(100000)
FORMAT Null;
结果
6666 rows in set. ...
max_execution_time
最大查询执行时间(以秒为单位)。此时,它不会针对任何一个排序阶段进行检查,也不会在合并和完成聚合函数时进行检查。
max_execution_time
参数可能有点难以理解。它基于相对于当前查询执行速度的插值来运作(此行为受 timeout_before_checking_execution_speed 控制)。如果预计执行时间超过指定的 max_execution_time
,ClickHouse 将中断查询。默认情况下,timeout_before_checking_execution_speed 设置为 10 秒。这意味着查询执行 10 秒后,ClickHouse 将开始估计总执行时间。例如,如果 max_execution_time
设置为 3600 秒(1 小时),如果估计时间超过此 3600 秒限制,ClickHouse 将终止查询。如果将 timeout_before_checking_execution_speed
设置为 0,ClickHouse 将使用时钟时间作为 max_execution_time
的依据。
timeout_overflow_mode
如果查询运行时间超过 max_execution_time
或估计运行时间超过 max_estimated_execution_time
,该怎么做:throw
或 break
。默认情况下,为 throw
。
max_execution_time_leaf
语义类似于 max_execution_time
,但仅适用于分布式或远程查询的叶节点。
例如,如果我们希望将叶节点上的执行时间限制为 10 秒
,但对初始节点没有限制,而不是在嵌套子查询设置中使用 max_execution_time
SELECT count() FROM cluster(cluster, view(SELECT * FROM t SETTINGS max_execution_time = 10));
我们可以使用 max_execution_time_leaf
作为查询设置
SELECT count() FROM cluster(cluster, view(SELECT * FROM t)) SETTINGS max_execution_time_leaf = 10;
timeout_overflow_mode_leaf
当叶节点中的查询运行时间超过 max_execution_time_leaf
时,该怎么做:throw
或 break
。默认情况下,为 throw
。
min_execution_speed
每秒最小执行速度(以行数计)。在 ‘timeout_before_checking_execution_speed’ 到期时,会针对每个数据块进行检查。如果执行速度较低,则会抛出异常。
min_execution_speed_bytes
每秒最小执行字节数。在 ‘timeout_before_checking_execution_speed’ 到期时,会针对每个数据块进行检查。如果执行速度较低,则会抛出异常。
max_execution_speed
每秒最大执行行数。在 ‘timeout_before_checking_execution_speed’ 到期时,会针对每个数据块进行检查。如果执行速度很高,则会降低执行速度。
max_execution_speed_bytes
每秒最大执行字节数。在 ‘timeout_before_checking_execution_speed’ 到期时,会针对每个数据块进行检查。如果执行速度很高,则会降低执行速度。
timeout_before_checking_execution_speed
在指定的秒数到期后,检查执行速度是否过慢(不低于 ‘min_execution_speed’)。
max_estimated_execution_time
最大查询估计执行时间(以秒为单位)。在 ‘timeout_before_checking_execution_speed’ 到期时,会针对每个数据块进行检查。
max_columns_to_read
可以从表中读取的最大列数,一次查询可以读取的列数。如果查询需要读取更多列,则会抛出异常。
max_temporary_columns
运行查询时必须同时保存在 RAM 中的最大临时列数,包括常量列。如果临时列多于此数,则会抛出异常。
max_temporary_non_const_columns
与 ‘max_temporary_columns’ 相同,但不计算常量列。请注意,运行查询时常量列的形成相当频繁,但它们需要大约为零的计算资源。
max_subquery_depth
子查询的最大嵌套深度。如果子查询更深,则会抛出异常。默认情况下,为 100。
max_pipeline_depth
最大管道深度。对应于每个数据块在查询处理过程中经过的转换次数。在单个服务器的限制内进行计数。如果管道深度更大,则会抛出异常。默认情况下,为 1000。
max_ast_depth
查询语法树的最大嵌套深度。如果超过此值,则会抛出异常。此时,它不会在解析过程中进行检查,而是在解析查询后才进行检查。也就是说,解析过程中可能会创建过深的语法树,但查询将失败。默认情况下,为 1000。
max_ast_elements
查询语法树中元素的最大数量。如果超过此值,则会抛出异常。与之前的设置一样,它仅在解析查询后才进行检查。默认情况下,为 50,000。
max_rows_in_set
从子查询创建的 IN 子句中数据集的最大行数。
max_bytes_in_set
从子查询创建的 IN 子句中使用的集合的最大字节数(未压缩数据)。
set_overflow_mode
当数据量超过任何一个限制时,该怎么做:‘throw’ 或 ‘break’。默认情况下,为 ‘throw’。
max_rows_in_distinct
使用 DISTINCT 时,不同行的最大数量。
max_bytes_in_distinct
使用 DISTINCT 时,哈希表使用的最大字节数。
distinct_overflow_mode
当数据量超过任何一个限制时,该怎么做:‘throw’ 或 ‘break’。默认情况下,为 ‘throw’。
max_rows_to_transfer
使用 GLOBAL IN 时,可以传递到远程服务器或保存在临时表中的最大行数。
max_bytes_to_transfer
使用 GLOBAL IN 时,可以传递到远程服务器或保存在临时表中的最大字节数(未压缩数据)。
transfer_overflow_mode
当数据量超过任何一个限制时,该怎么做:‘throw’ 或 ‘break’。默认情况下,为 ‘throw’。
max_rows_in_join
限制在连接表时使用的哈希表中的行数。
此设置适用于 SELECT ... JOIN 操作和 Join 表引擎。
如果查询包含多个连接,ClickHouse 会针对每个中间结果检查此设置。
当达到限制时,ClickHouse 可以继续执行不同的操作。使用 join_overflow_mode 设置选择操作。
可能的值
- 正整数。
- 0 — 行数无限制。
默认值:0。
max_bytes_in_join
限制连接表时使用的哈希表的大小(以字节为单位)。
此设置适用于 SELECT ... JOIN 操作和 Join 表引擎。
如果查询包含连接,ClickHouse 会针对每个中间结果检查此设置。
当达到限制时,ClickHouse 可以继续执行不同的操作。使用 join_overflow_mode 设置选择操作。
可能的值
- 正整数。
- 0 — 内存控制已禁用。
默认值:0。
join_overflow_mode
定义当达到以下任何连接限制时,ClickHouse 执行的操作
可能的值
THROW
— ClickHouse 抛出异常并中断操作。BREAK
— ClickHouse 中断操作,但不抛出异常。
默认值:THROW
。
另请参见
max_partitions_per_insert_block
限制单个插入块中的最大分区数。
- 正整数。
- 0 — 分区数无限制。
默认值:100。
详细信息
插入数据时,ClickHouse 会计算插入块中的分区数。如果分区数超过 max_partitions_per_insert_block
,ClickHouse 会根据 throw_on_max_partitions_per_insert_block
记录警告或抛出异常。异常具有以下文本
“单个 INSERT 块的分区过多(
partitions_count
个分区,限制为 ” + toString(max_partitions) + “)。此限制由 ‘max_partitions_per_insert_block’ 设置控制。分区数量过多是一个常见的误解,会导致严重的负面性能影响,包括服务器启动缓慢、INSERT 查询速度慢以及 SELECT 查询速度慢。建议表的分区总数在 1000 到 10000 之间。请注意,分区并非旨在加速 SELECT 查询(ORDER BY key 足以使范围查询速度更快)。分区用于数据操作(DROP PARTITION 等)。”
throw_on_max_partitions_per_insert_block
允许您控制达到 max_partitions_per_insert_block
时的行为。
true
- 当插入块达到max_partitions_per_insert_block
时,会抛出异常。false
- 当达到max_partitions_per_insert_block
时,会记录警告。
默认值:true
max_temporary_data_on_disk_size_for_user
所有并发运行的用户查询在磁盘上临时文件所消耗的最大数据量(字节)。零表示无限制。
默认值:0。
max_temporary_data_on_disk_size_for_query
所有并发运行的查询在磁盘上临时文件所消耗的最大数据量(字节)。零表示无限制。
默认值:0。
max_sessions_for_user
每个经过身份验证的用户对 ClickHouse 服务器的最大并发会话数。
示例
<profiles>
<single_session_profile>
<max_sessions_for_user>1</max_sessions_for_user>
</single_session_profile>
<two_sessions_profile>
<max_sessions_for_user>2</max_sessions_for_user>
</two_sessions_profile>
<unlimited_sessions_profile>
<max_sessions_for_user>0</max_sessions_for_user>
</unlimited_sessions_profile>
</profiles>
<users>
<!-- User Alice can connect to a ClickHouse server no more than once at a time. -->
<Alice>
<profile>single_session_user</profile>
</Alice>
<!-- User Bob can use 2 simultaneous sessions. -->
<Bob>
<profile>two_sessions_profile</profile>
</Bob>
<!-- User Charles can use arbitrarily many of simultaneous sessions. -->
<Charles>
<profile>unlimited_sessions_profile</profile>
</Charles>
</users>
默认值:0(并发会话数无限制)。
max_partitions_to_read
限制一个查询可以访问的最大分区数。
创建表时指定的设置值可以通过查询级设置覆盖。
可能的值
- 任何正整数。
默认值:-1(无限制)。
您也可以在表的设置中指定 MergeTree 设置 max_partitions_to_read。