只有在 enable_analyzer 设置为 true 时,查询条件缓存才会生效,而这也是默认值。
WHERE col = 'xyz') 进行求值,始终会得到相同的结果。
更具体地说,对于每个已求值的过滤器和每个粒度 (即一个块,默认包含 8192 行) ,查询条件缓存都会记录该粒度中是否没有任何行满足该过滤条件。
这些信息会以单个比特位的形式记录:0 表示没有任何行匹配该过滤器,1 表示至少有一行匹配。
在前一种情况下,ClickHouse 可以在求值过滤条件时跳过相应的粒度;在后一种情况下,则必须加载该粒度并进行求值。
当以下三个前置条件满足时,查询条件缓存会非常有效:
- 第一,工作负载必须重复求值相同的过滤条件。如果同一个查询被多次重复执行,这种情况会自然出现;如果两个查询使用了相同的过滤器,也会出现这种情况,例如
SELECT product FROM products WHERE quality > 3和SELECT vendor, count() FROM products WHERE quality > 3。 - 第二,大多数数据必须是不可变的,也就是说,在多次查询之间不会发生变化。在 ClickHouse 中,这通常成立,因为 parts 是不可变的,并且只会通过 INSERT 创建。
- 第三,过滤器必须具有较高的选择性,也就是说,只有相对较少的行满足过滤条件。匹配过滤条件的行越少,被记录为 0 比特位 (无匹配行) 的粒度就越多,后续求值过滤条件时可被“剪枝”的数据也就越多。
内存消耗
query_condition_cache_size 配置 (默认值:100 MB) 。
100 MB 的缓存大小对应 100 * 1024 * 1024 * 8 = 838,860,800 个条目。
由于每个条目代表一个标记 (默认情况下为 8192 行) ,因此该缓存最多可覆盖单列的 6,871,947,673,600 (6.8 万亿) 行。
在实际场景中,过滤条件通常会在多个列上求值,因此这个数字需要除以被过滤的列数。
配置项及用法
use_query_condition_cache = true,将利用查询条件缓存以减少扫描的数据量。
管理
SYSTEM CLEAR QUERY CONDITION CACHE。
缓存内容显示在系统表 system.query_condition_cache 中。
要以 MB 为单位计算当前查询条件缓存的大小,请运行 SELECT formatReadableSize(sum(entry_size)) FROM system.query_condition_cache。
如果你想查看单个过滤条件,可以检查 system.query_condition_cache 中的 condition 字段。请注意,该字段仅在 debug 构建中可用。
自数据库启动以来,查询条件缓存的命中次数和未命中次数会在系统表 system.events 中显示为事件 “QueryConditionCacheHits” 和 “QueryConditionCacheMisses”。
只有在设置 use_query_condition_cache = true 时运行的 SELECT 查询才会更新这两个计数器,其他查询不会影响 “QueryCacheMisses”。