ClickHouse 支持查詢結果緩存啦

今天我們要聊的是查詢結果緩存,在以往,這項功能要放在下游的應用層自行實現。自己時常會想,要是數據庫自己就有這個功能該多方便。

現在 ClickHouse 還真就內置這項功能了,從 V23.1 開始引入了查詢結果緩存,支持 SELECT 結果緩存。在緩存 TTL 期間,基於 AST 語法樹分析,相同的 SELECT 將僅執行第一次查詢,後續查詢直接從緩存返回。

是不是很興奮呢?這還不趕快試試?

我們用官方的 一億的測試數據集 hits_100m_obfuscated 進行演示。

先試試沒有查詢緩存的感覺:

SELECT
    RegionID,
    uniq(UserID) AS u
FROM hits_100m_obfuscated
GROUP BY RegionID
ORDER BY u DESC
LIMIT 10
Query id: 2944d569-6d9f-49c9-9b82-2f2f81fcfbd4
┌─RegionID─┬───────u─┐
│      2292853403 │
│        21080698 │
│      208831401 │
│      169608301 │
│      184322302 │
│      158306236 │
│       34298706 │
│       55287611 │
│      107271657 │
│       42242793 │
└──────────┴─────────┘
10 rows in set. Elapsed: 0.819 sec. Processed 100.00 million rows, 1.20 GB (122.16 million rows/s., 1.47 GB/s.)

OK,現在步入正題,要使用查詢結果緩存,首先要開啓配置

SET allow_experimental_query_cache = true

然後在需要緩存的查詢後面帶上:

SETTINGS use_query_cache = true

例如第一次執行,會生成查詢結果緩存:

SELECT
    RegionID,
    uniq(UserID) AS u
FROM hits_100m_obfuscated
GROUP BY RegionID
ORDER BY u DESC
LIMIT 10
SETTINGS use_query_cache = 1
Query id: 18057c67-ac9a-4dca-815f-f741b4610a0b
┌─RegionID─┬───────u─┐
│      2292853403 │
│        21080698 │
│      208831401 │
│      169608301 │
│      184322302 │
│      158306236 │
│       34298706 │
│       55287611 │
│      107271657 │
│       42242793 │
└──────────┴─────────┘
10 rows in set. Elapsed: 0.869 sec. Processed 100.00 million rows, 1.20 GB (115.06 million rows/s., 1.38 GB/s.)

第二次執行,瞬間直接從緩存返回:

SELECT
    RegionID,
    uniq(UserID) AS u
FROM hits_100m_obfuscated
GROUP BY RegionID
ORDER BY u DESC
LIMIT 10
SETTINGS use_query_cache = 1
Query id: 89e1a32b-dc0a-4aa9-96cc-912531a34861
┌─RegionID─┬───────u─┐
│      2292853403 │
│        21080698 │
│      208831401 │
│      169608301 │
│      184322302 │
│      158306236 │
│       34298706 │
│       55287611 │
│      107271657 │
│       42242793 │
└──────────┴─────────┘
10 rows in set. Elapsed: 0.006 sec.

是不是很爽呢?

從資源消耗層面看看緩存的威力吧,查看緩存命中率和資源消耗:

SELECT
    query,
    ProfileEvents['QueryCacheHits'] AS query_cache,
    query_duration_ms / 1000 AS query_duration,
    formatReadableSize(memory_usage) AS memory_usage,
    formatReadableQuantity(read_rows) AS read_rows,
    formatReadableSize(read_bytes) AS read_data
FROM system.query_log
WHERE (type = 'QueryFinish') AND hasAll(tables, ['cluster_test.hits_100m_obfuscated'])
ORDER BY initial_query_start_time DESC
LIMIT 2
FORMAT Vertical
Query id: 05f101cf-e250-4d3a-9fbb-cb62daf90956
Row 1:
──────
query:          SELECT RegionID, uniq(UserID) AS u FROM hits_100m_obfuscated 
GROUP BY RegionID ORDER BY u DESC LIMIT 10
SETTINGS use_query_cache = true;
query_cache:    1
query_duration: 0.005
memory_usage:   17.27 KiB
read_rows:      10.00
read_data:      120.00 B
Row 2:
──────
query:          SELECT RegionID, uniq(UserID) AS u FROM hits_100m_obfuscated 
GROUP BY RegionID ORDER BY u DESC LIMIT 10
SETTINGS use_query_cache = true;
query_cache:    0
query_duration: 0.813
memory_usage:   241.74 MiB
read_rows:      100.00 million
read_data:      1.12 GiB

時間: 0.005 vs 0.813

內存:17.27K vs 241.74MB

除了上面這條運維 SQL 以外,我們還可以從系統表看到緩存信息:

SELECT *
FROM system.query_cache
FORMAT Vertical
Query id: e10857e9-da10-4b53-892a-b9a4707c6216
Row 1:
──────
query:       SELECT RegionID, uniq(UserID) AS u FROM hits_100m_obfuscated GROUP BY RegionID ORDER BY u DESC LIMIT 10 SETTINGS 
result_size: 512
stale:       1
shared:      1
compressed:  1
expires_at:  2023-06-24 11:28:20
key_hash:    16226283579053502780

可以清楚的看到當前緩存了哪些 SQL,是否過期。

在使用 ClickHouse 查詢結果緩存的時候,還有 2 點需要值得注意:

SELECT 結果緩存的 TTL 時間默認是 60 秒,可以自行設置,超過了時間之後緩存會失效,例如將時間改爲 2 秒:

SELECT RegionID, uniq(UserID) AS u FROM hits_100m_obfuscated 
GROUP BY RegionID ORDER BY u DESC LIMIT 10
SETTINGS use_query_cache = true ,query_cache_ttl = 2;

2 秒以後再次查詢,不會走緩存。

2、緩存大小

單個 SELECT 查詢結果緩存大小限制默認 1M,超過 1M 的結果不會被緩存,例如下面這條返回字符串的 SQL,不能被緩存:

SELECT URL AS u FROM hits_100m_obfuscated  LIMIT 1000000
FORMAT `Null`
SETTINGS use_query_cache = true;

查詢日誌會發現超過閾值的提示:

QueryCache: Skipped insert (query result too big), new_entry_size_in_bytes: 1179648 (1048576), new_entry_size_in_rows: 10653 (30000000)

當前我們可以在 cong.xml 修改閾值,包括緩存大小、個數等:

<query_cache>
    <size>1073741824</size>
    <max_entries>1024</max_entries>
    <max_entry_size>1048576</max_entry_size>
    <max_entry_records>30000000</max_entry_records>
</query_cache>

總體來說,ClickHouse 內置的查詢結果緩存還方便的,趕快去試試吧

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/7EFPFTSSQJ8N8b3mIgWZ9Q