跳至主要内容

·阅读时间:2 分钟

如果列是稀疏的(为空或大部分包含零),ClickHouse 可以将它编码为稀疏格式并自动优化计算 - 数据在查询期间不需要完全解压缩。实际上,如果您知道列的稀疏程度,可以使用 ratio_of_defaults_for_sparse_serialization 设置 定义其比率以优化序列化。

这个方便的查询可能需要一段时间,但它会分析表中的每一行并确定指定表中每列中值为零(或默认值)的比率

SELECT *
APPLY x -> (x = defaultValueOfArgumentType(x)) APPLY avg APPLY x -> round(x, 3)
FROM table_name
FORMAT Vertical

例如,我们在上面的 环境传感器数据集 表名为 sensors 上运行了此查询,该表有超过 200 亿行和 19 列

SELECT *
APPLY x -> (x = defaultValueOfArgumentType(x)) APPLY avg APPLY x -> round(x, 3)
FROM sensors
FORMAT Vertical

以下是响应


Row 1:
──────
round(avg(equals(sensor_id, defaultValueOfArgumentType(sensor_id))), 3): 0
round(avg(equals(sensor_type, defaultValueOfArgumentType(sensor_type))), 3): 0.159
round(avg(equals(location, defaultValueOfArgumentType(location))), 3): 0
round(avg(equals(lat, defaultValueOfArgumentType(lat))), 3): 0.001
round(avg(equals(lon, defaultValueOfArgumentType(lon))), 3): 0.001
round(avg(equals(timestamp, defaultValueOfArgumentType(timestamp))), 3): 0
round(avg(equals(P1, defaultValueOfArgumentType(P1))), 3): 0.474
round(avg(equals(P2, defaultValueOfArgumentType(P2))), 3): 0.475
round(avg(equals(P0, defaultValueOfArgumentType(P0))), 3): 0.995
round(avg(equals(durP1, defaultValueOfArgumentType(durP1))), 3): 0.999
round(avg(equals(ratioP1, defaultValueOfArgumentType(ratioP1))), 3): 0.999
round(avg(equals(durP2, defaultValueOfArgumentType(durP2))), 3): 1
round(avg(equals(ratioP2, defaultValueOfArgumentType(ratioP2))), 3): 1
round(avg(equals(pressure, defaultValueOfArgumentType(pressure))), 3): 0.83
round(avg(equals(altitude, defaultValueOfArgumentType(altitude))), 3): 1
round(avg(equals(pressure_sealevel, defaultValueOfArgumentType(pressure_sealevel))), 3): 1
round(avg(equals(temperature, defaultValueOfArgumentType(temperature))), 3): 0.532
round(avg(equals(humidity, defaultValueOfArgumentType(humidity))), 3): 0.544

1 row in set. Elapsed: 992.041 sec. Processed 20.69 billion rows, 1.39 TB (20.86 million rows/s., 1.40 GB/s.)

从以上结果

  • sensor_id 列根本不稀疏。实际上,每一行都有一个非零值
  • sensor_type 只有大约 15.9% 的时间是稀疏的
  • P0 列非常稀疏:99.9% 的值为零
  • pressure 列在 83% 时相当稀疏
  • temperature 列有 53.2% 的值缺失或为零

正如我们所说,这是一个计算 ClickHouse 表中列的稀疏程度的便捷查询!

·阅读时间:2 分钟

问题

如何验证两个查询是否返回相同的结果集?

答案

您可以使用以下方法

WITH
(
SELECT sum(cityHash64(*))
FROM
(
-- your query 1 here
-- SELECT ...
)
) AS q1_resultset_hash,
(
SELECT sum(cityHash64(*))
FROM
(
-- your query 2 here
-- SELECT ...
)
) AS q2_resultset_hash
SELECT equals(q1_resultset_hash,q2_resultset_hash) as Q1_equals_Q2

此示例使用 CTE 计算这两个查询中每一行的 cityHash 值的总和,如果两个结果集相同,则返回 1

使用一些整数序列数据和一些漂亮的格式

WITH
(
SELECT sum(cityHash64(*))
FROM
(
SELECT *
FROM numbers(10)
ORDER BY number DESC
)
) AS q1_resultset_hash,
(
SELECT sum(cityHash64(*))
FROM
(
SELECT *
FROM numbers(10)
ORDER BY number ASC
)
) AS q2_resultset_hash
SELECT q1_resultset_hash = q2_resultset_hash AS Q1_equals_Q2
FORMAT Pretty

将返回

┏━━━━━━━━━━━━━━┓
┃ Q1_equals_Q2 ┃
┡━━━━━━━━━━━━━━┩
│ 1 │
└──────────────┘

虽然这在许多情况下非常有用,但不能将其视为验证所有类型结果集相等性的灵丹妙药,并且使用它有一些注意事项,例如,如果任何行包含 NULL 值,则上述方法将失败。

·阅读时间:1 分钟

错误的原因

此错误在尝试使用 clickhouse-client 连接到 ClickHouse 服务器时发生。错误的原因可能是

  • 客户端配置文件 config.xml 缺少机器 CA 默认存储中的根证书,或者
  • 存在未配置的自签名或内部 CA 证书

解决方案

如果使用内部或自签名 CA,请在客户端目录(例如 /etc/clickhouse-client)中在 config.xml 中配置 CA 根证书,并禁用从默认位置加载默认根 CA 证书。

这是一个配置示例

<openSSL>
<client>
<loadDefaultCAFile>false</loadDefaultCAFile>
<caConfig>/etc/clickhouse-server/certs/marsnet_ca.crt</caConfig>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
<invalidCertificateHandler>
<name>RejectCertificateHandler</name>
</invalidCertificateHandler>
</client>
</openSSL>

附加资源

查看 https://clickhouse.ac.cn/docs/en/interfaces/cli/#configuration_files

·阅读时间:2 分钟

当出现此错误时,表格将显示为只读,并且错误指出相交的部分。您可以在日志中或通过以下方式查看错误:

SELECT *
FROM system.replicas
WHERE is_readonly = 1

错误消息看起来像这样

Code: 49. DB::Exception: Part XXXXX intersects previous part YYYYY. It is a bug or a result of manual intervention in the ZooKeeper data. (LOGICAL_ERROR) (version 21.12.4.1 (official build))

错误的原因

此错误可能是由mergeSelectingTask 和队列重新初始化之间的竞争条件引起的。

解决方案

在所有副本上执行以下查询

DETACH TABLE table_name;  -- Required for DROP REPLICA

SYSTEM DROP REPLICA 'replica_name' FROM ZK PATH '/table_path_in_zk/'; -- It will remove everything from /table_path_in_zk

ATTACH TABLE table_name; -- Table will be in readonly mode, because there is no metadata in ZK

然后在所有副本上执行以下操作

SYSTEM RESTORE REPLICA table_name;  -- It will detach all partitions, re-create metadata in ZK (like it's new empty table), and then attach all partitions back

SYSTEM SYNC REPLICA table_name; -- Wait for replicas to synchronize parts. Also it's recommended to check `system.detached_parts` on all replicas after recovery is finished.
小贴士

您应该升级到最新版本的 ClickHouse

附加资源

相关 PR 和 GitHub 问题

受影响的版本:

ClickHouse v 22.12 及更早版本

·阅读时间:3 分钟

TTL 将**最终**应用。这是什么意思?MergeTree 表设置 merge_with_ttl_timeout 设置了重复进行删除 TTL 合并的最小延迟时间(以秒为单位)。默认值为 14400 秒(4 小时)。但这只是最小延迟,触发删除 TTL 合并可能需要更长时间。

您可以使用此查询查看所有当前的 TTL 设置(如 merge_with_ttl_timeout

SELECT *
FROM system.merge_tree_settings
WHERE name like '%ttl%'

响应看起来像这样

┌─name───────────────────────────────────────────────────────────┬─value───┬─changed─┬─description────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─min──┬─max──┬─readonly─┬─type───┐
│ max_replicated_merges_with_ttl_in_queue │ 1 │ 0 │ How many tasks of merging parts with TTL are allowed simultaneously in ReplicatedMergeTree queue. │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ 0 │ UInt64 │
│ max_number_of_merges_with_ttl_in_pool │ 2 │ 0 │ When there is more than specified number of merges with TTL entries in pool, do not assign new merge with TTL. This is to leave free threads for regular merges and avoid "Too many parts" │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ 0 │ UInt64 │
│ merge_tree_clear_old_broken_detached_parts_ttl_timeout_seconds │ 2592000 │ 1 │ Remove old broken detached parts in the background if they remained intouched for a specified by this setting period of time. │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ 0 │ UInt64 │
│ merge_with_ttl_timeout │ 14400 │ 0 │ Minimal time in seconds, when merge with delete TTL can be repeated. │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ 0 │ Int64 │
│ merge_with_recompression_ttl_timeout │ 14400 │ 0 │ Minimal time in seconds, when merge with recompression TTL can be repeated. │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ 0 │ Int64 │
│ ttl_only_drop_parts │ 0 │ 0 │ Only drop altogether the expired parts and not partially prune them. │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ 0 │ Bool │
│ materialize_ttl_recalculate_only │ 0 │ 0 │ Only recalculate ttl info when MATERIALIZE TTL │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ 0 │ Bool │
└────────────────────────────────────────────────────────────────┴─────────┴─────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────┴──────┴──────────┴────────┘

您可以使用 SHOW CREATE TABLE 检查您的表格是否包含 TTL 规则,以及表格中的任何 SETTINGS 是否修改了上述设置的值

SHOW CREATE TABLE <TableName>

强制应用 TTL 规则

这不是最优雅的解决方案,但您可以显式调用 MATERIALIZE TTL,这会强制将表格的所有 TTL 规则具体化

ALTER TABLE my_table
MATERIALIZE TTL

影响 TTL 的后台线程

您的 TTL 规则可能无法应用,因为后台池中没有足够的活动线程。例如,如果您大量插入数据,则整个后台池可能会被用于正常合并。但是,您可以增加后台池大小。

您可以使用此查询检查当前的后台池大小

SELECT *
FROM system.settings
WHERE name = 'background_pool_size';

响应看起来像这样

┌─name─────────────────┬─value─┬─changed─┬─description─────────────────────┬─min──┬─max──┬─readonly─┬─type───┬─default─┬─alias_for─┐
│ background_pool_size │ 16 │ 0 │ Obsolete setting, does nothing. │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ 0 │ UInt64 │ 16 │ │
└──────────────────────┴───────┴─────────┴─────────────────────────────────┴──────┴──────┴──────────┴────────┴─────────┴───────────┘

查看文档以了解如何修改 background_pool_size 设置,该设置配置为

<background_pool_size>16</background_pool_size>

您可以使用此查询检查当前的后台池活动

SELECT *
FROM system.metrics
WHERE metric like 'Background%'

·阅读时间:3 分钟

如何在 Microsoft Windows 上安装和测试 ClickHouse

在 Windows 10 上安装 ClickHouse 时,您可能会在插入数据时收到错误,例如

DB::Exception: std::__1::__fs::filesystem::filesystem_error: filesystem error: in rename: Permission denied ["./store/711/71144174-d098-4056-8976-6ad1204205ec/tmp_insert_all_1_1_0/"] ["./store/711/71144174-d098-4056-8976-6ad1204205ec/all_1_1_0/"]. Stack trace:

在 Windows 10 上,需要将 WSL 升级到 WSL 2。

wsl
  • 对于测试,请按照以下说明操作,您应该会看到类似的输出:由于这是为了测试,我以 root 用户身份登录以避免权限问题
sudo -i
  • 创建一个 ClickHouse 目录
root@marspc2:~# mkdir /clickhouse
  • 从新目录中下载 clickhouse
root@marspc2:/# cd clickhouse

root@marspc2:/clickhouse# curl https://clickhouse.ac.cn | sh
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2739 0 2739 0 0 5515 0 --:--:-- --:--:-- --:--:-- 5511

Will download https://builds.clickhouse.com/master/amd64/clickhouse into clickhouse

% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 530M 100 530M 0 0 8859k 0 0:01:01 0:01:01 --:--:-- 8549k

Successfully downloaded the ClickHouse binary, you can run it as:
./clickhouse

You can also install it:
sudo ./clickhouse install
  • 启动 clickhouse 服务器
root@marspc2:/clickhouse# ./clickhouse server
Processing configuration file 'config.xml'.
There is no file 'config.xml', will use embedded config.
Cannot set max size of core file to 1073741824
2023.04.17 19:19:23.155323 [ 500 ] {} <Information> SentryWriter: Sending crash reports is disabled
2023.04.17 19:19:23.165447 [ 500 ] {} <Trace> Pipe: Pipe capacity is 1.00 MiB
2023.04.17 19:19:23.271147 [ 500 ] {} <Information> Application: Starting ClickHouse 23.4.1.1222 (revision: 54473, git hash: 3993aef8e281815ac4269d44e27bb1dcdcff21cb, build id: AF16AA59B689841860F39ACDBED30AC8F9AB70FA), PID 500
2023.04.17 19:19:23.271208 [ 500 ] {} <Information> Application: starting up
2023.04.17 19:19:23.271237 [ 500 ] {} <Information> Application: OS name: Linux, version: 5.15.90.1-microsoft-standard-WSL2, architecture: x86_64
...
  • 在另一个 WSL 窗口中,启动客户端
root@marspc2:/clickhouse# ./clickhouse client
ClickHouse client version 23.4.1.1222 (official build).
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 23.4.1 revision 54462.

Warnings:
* Linux transparent hugepages are set to "always". Check /sys/kernel/mm/transparent_hugepage/enabled

marspc2. :)
  • 创建数据库和表格
marspc2. :) create database db1;

CREATE DATABASE db1

Query id: 688f79e2-8132-44ed-98d6-0581abe9903a

Ok.

0 rows in set. Elapsed: 0.007 sec.

marspc2. :) create table db1.table1 (id Int64, string_column String) engine = MergeTree() order by id;

CREATE TABLE db1.table1
(
`id` Int64,
`string_column` String
)
ENGINE = MergeTree
ORDER BY id

Query id: d91a93b4-e13f-4e17-8201-f329223287d0

Ok.

0 rows in set. Elapsed: 0.010 sec.
  • 插入示例行
marspc2. :) insert into db1.table1 (id, string_column) values (1, 'a'), (2,'b');

INSERT INTO db1.table1 (id, string_column) FORMAT Values

Query id: 2b274eef-09af-434b-88e0-c25799649910

Ok.

2 rows in set. Elapsed: 0.003 sec.
  • 查看行
marspc2. :) select * from db1.table1;

SELECT *
FROM db1.table1

Query id: 74c76bf1-d944-4b21-a384-cc0b5e6aa579

┌─id─┬─string_column─┐
│ 1 │ a │
│ 2 │ b │
└────┴───────────────┘

2 rows in set. Elapsed: 0.002 sec.

·阅读时间:6 分钟

system 数据库中的 query_log 表跟踪所有查询,包括

  • 查询消耗了多少内存,以及
  • 需要多少 CPU 时间

以下查询返回前 10 个查询,其中“前 10 个”是指使用最多内存的查询

SELECT
type,
event_time,
initial_query_id,
query_id,
formatReadableSize(memory_usage) AS memory,
ProfileEvents.Values[indexOf(ProfileEvents.Names, 'UserTimeMicroseconds')] AS userCPU,
ProfileEvents.Values[indexOf(ProfileEvents.Names, 'SystemTimeMicroseconds')] AS systemCPU,
normalizedQueryHash(query) AS normalized_query_hash
FROM clusterAllReplicas(default, system.query_log)
ORDER BY memory_usage DESC
LIMIT 10;

响应看起来像这样

┌─type────────┬──────────event_time─┬─initial_query_id─────────────────────┬─memory─────┬─────userCPU─┬──systemCPU─┬─normalized_query_hash─┐
│ QueryFinish │ 2023-03-26 21:36:07 │ 7fc488a5-838f-410d-88ee-2f492825a26b │ 3.45 GiB │ 28147128901 │ 8590897697 │ 178963678599600243 │
│ QueryFinish │ 2023-03-26 21:36:04 │ 7fc488a5-838f-410d-88ee-2f492825a26b │ 1.18 GiB │ 10194162387 │ 1183376457 │ 4121209451971717712 │
│ QueryFinish │ 2023-03-26 21:36:06 │ 7fc488a5-838f-410d-88ee-2f492825a26b │ 1.16 GiB │ 10516510952 │ 1484303318 │ 4121209451971717712 │
│ QueryFinish │ 2023-03-26 21:35:59 │ 7fc488a5-838f-410d-88ee-2f492825a26b │ 1.14 GiB │ 11484580963 │ 1464145099 │ 4121209451971717712 │
│ QueryFinish │ 2023-03-26 21:47:01 │ 8119e682-a343-4847-96e7-d34ad8a748a1 │ 455.29 MiB │ 123340498 │ 8234304 │ 10687606311941357470 │
│ QueryFinish │ 2023-03-26 22:07:05 │ f2690e48-fe1e-4367-ae9d-435d962003a5 │ 377.94 MiB │ 2358130001 │ 668098391 │ 5988812223780974416 │
│ QueryFinish │ 2023-03-26 20:45:42 │ 04618222-40a1-4299-8c3d-9f050a82d849 │ 18.48 MiB │ 24676 │ 16620 │ 3205198713665290475 │
│ QueryFinish │ 2023-03-26 22:14:37 │ badf1097-5f8f-4486-88e9-3a5ac2e4734c │ 17.41 MiB │ 186234 │ 148739 │ 1910846996890686559 │
│ QueryFinish │ 2023-03-26 21:39:42 │ 8d373327-f566-4cd5-9f2c-cec75f534751 │ 16.19 MiB │ 23169 │ 12365 │ 3205198713665290475 │
│ QueryFinish │ 2023-03-26 21:35:42 │ ea672dba-7c10-4dd4-b819-cad9dccbf5d0 │ 13.97 MiB │ 20696 │ 8001 │ 3205198713665290475 │
└─────────────┴─────────────────────┴──────────────────────────────────────┴────────────┴─────────────┴────────────┴───────────────────────┘
注意

initial_query_id 表示从接收请求的节点启动的分布式查询执行的初始查询的 ID。query_id 包含在不同节点上执行的子查询的 ID。有关更多详细信息,请参阅 本文

您可以使用查询 ID 提取有关查询的更多详细信息。让我们研究一下上面运行时间最长的查询(第一个查询)

SELECT query
FROM clusterAllReplicas(default, system.query_log)
WHERE initial_query_id = '7fc488a5-838f-410d-88ee-2f492825a26b'

事实证明,这是我们用于将数十亿行数据插入名为 youtube 的表格中的查询(请参阅 YouTube 不喜欢数据集

INSERT INTO youtube
SETTINGS input_format_null_as_default = 1
SELECT
id,
parseDateTimeBestEffortUS(toString(fetch_date)) AS fetch_date,
upload_date,
ifNull(title, '') AS title,
uploader_id,
ifNull(uploader, '') AS uploader,
uploader_sub_count,
is_age_limit,
view_count,
like_count,
dislike_count,
is_crawlable,
has_subtitles,
is_ads_enabled,
is_comments_enabled,
ifNull(description, '') AS description,
rich_metadata,
super_titles,
ifNull(uploader_badges, '') AS uploader_badges,
ifNull(video_badges, '') AS video_badges
FROM s3Cluster('default','https://clickhouse-public-datasets.s3.amazonaws.com/youtube/original/files/*.zst', 'JSONLines')

initial_query_id VS query_id

请注意,在集群化的 ClickHouse 环境(如 ClickHouse Cloud)中,initial_query_id 表示从接收请求的节点启动的分布式查询执行的初始查询的 ID;然后 query_id 字段将包含在不同节点上执行的子查询的 ID。

如果我们在上述查询中添加 query_id,我们将围绕 initial_query_id = a7262fa2-bd8b-4b51-a359-621ccf282417hostname() 进行搜索

SELECT
hostname(),
type,
event_time,
initial_query_id,
query_id,
formatReadableSize(memory_usage) AS memory,
ProfileEvents.Values[indexOf(ProfileEvents.Names, 'UserTimeMicroseconds')] AS userCPU,
ProfileEvents.Values[indexOf(ProfileEvents.Names, 'SystemTimeMicroseconds')] AS systemCPU,
normalizedQueryHash(query) AS normalized_query_hash
FROM clusterAllReplicas(default, system.query_log)
WHERE initial_query_id = 'a7262fa2-bd8b-4b51-a359-621ccf282417'
ORDER BY memory_usage DESC
LIMIT 10 FORMAT Pretty;

我们将得到

┏━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ hostname() ┃ type ┃ event_time ┃ initial_query_id ┃ query_id ┃ memory ┃ userCPU ┃ systemCPU ┃ normalized_query_hash ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ server-0 │ QueryFinish │ 2023-04-26 06:25:53 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 1f810b3c-b3cb-4a7b-bc6c-8c8cc1e52515 │ 125.13 MiB │ 1754290 │ 133344 │ 17604798521132779336 │
├────────────────────────┼─────────────┼─────────────────────┼──────────────────────────────────────┼──────────────────────────────────────┼────────────┼─────────┼───────────┼───────────────────────┤
│ server-2 │ QueryFinish │ 2023-04-26 06:25:53 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 123.08 MiB │ 1849115 │ 123412 │ 4258439895846105173 │
└────────────────────────┴─────────────┴─────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴────────────┴─────────┴───────────┴───────────────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ hostname() ┃ type ┃ event_time ┃ initial_query_id ┃ query_id ┃ memory ┃ userCPU ┃ systemCPU ┃ normalized_query_hash ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ server-1 │ QueryFinish │ 2023-04-26 06:25:53 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 7dfd9297-5173-4be7-a866-d7cbe1e1abab │ 93.77 MiB │ 1890981 │ 101724 │ 17604798521132779336 │
├────────────────────────┼─────────────┼─────────────────────┼──────────────────────────────────────┼──────────────────────────────────────┼───────────┼─────────┼───────────┼───────────────────────┤
│ server-1 │ QueryStart │ 2023-04-26 06:25:52 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 7dfd9297-5173-4be7-a866-d7cbe1e1abab │ 0.00 B │ 0 │ 0 │ 17604798521132779336 │
└────────────────────────┴─────────────┴─────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴───────────┴─────────┴───────────┴───────────────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ hostname() ┃ type ┃ event_time ┃ initial_query_id ┃ query_id ┃ memory ┃ userCPU ┃ systemCPU ┃ normalized_query_hash ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ server-0 │ QueryStart │ 2023-04-26 06:25:52 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 1f810b3c-b3cb-4a7b-bc6c-8c8cc1e52515 │ 0.00 B │ 0 │ 0 │ 17604798521132779336 │
├────────────────────────┼────────────┼─────────────────────┼──────────────────────────────────────┼──────────────────────────────────────┼────────┼─────────┼───────────┼───────────────────────┤
│ server-2 │ QueryStart │ 2023-04-26 06:25:52 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 0.00 B │ 0 │ 0 │ 4258439895846105173 │
└────────────────────────┴────────────┴─────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴────────┴─────────┴───────────┴───────────────────────┘

请注意,我们从几个主机(不同的集群节点)获得了几个结果。

为了进一步细化并仅获取子查询,我们还可以将 query_id != initial_query_id 条件添加到 WHERE 子句中

SELECT
hostname(),
type,
event_time,
initial_query_id,
query_id,
formatReadableSize(memory_usage) AS memory,
ProfileEvents.Values[indexOf(ProfileEvents.Names, 'UserTimeMicroseconds')] AS userCPU,
ProfileEvents.Values[indexOf(ProfileEvents.Names, 'SystemTimeMicroseconds')] AS systemCPU,
normalizedQueryHash(query) AS normalized_query_hash
FROM clusterAllReplicas(default, system.query_log)
WHERE (query_id = initial_query_id) AND (initial_query_id = 'a7262fa2-bd8b-4b51-a359-621ccf282417')
ORDER BY memory_usage DESC
LIMIT 10 FORMAT Pretty;

返回在远程节点(对于第一个抛出查询的节点而言是远程的)上执行的所有子查询

┏━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ hostname() ┃ type ┃ event_time ┃ initial_query_id ┃ query_id ┃ memory ┃ userCPU ┃ systemCPU ┃ normalized_query_hash ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ server-1 │ QueryFinish │ 2023-04-26 06:25:53 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 7dfd9297-5173-4be7-a866-d7cbe1e1abab │ 93.77 MiB │ 1890981 │ 101724 │ 17604798521132779336 │
├────────────────────────┼─────────────┼─────────────────────┼──────────────────────────────────────┼──────────────────────────────────────┼────────────┼─────────┼───────────┼───────────────────────┤
│ server-0 │ QueryFinish │ 2023-04-26 06:25:53 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 1f810b3c-b3cb-4a7b-bc6c-8c8cc1e52515 │ 125.13 MiB │ 1754290 │ 133344 │ 17604798521132779336 │
├────────────────────────┼─────────────┼─────────────────────┼──────────────────────────────────────┼──────────────────────────────────────┼────────────┼─────────┼───────────┼───────────────────────┤
│ server-1 │ QueryStart │ 2023-04-26 06:25:52 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 7dfd9297-5173-4be7-a866-d7cbe1e1abab │ 0.00 B │ 0 │ 0 │ 17604798521132779336 │
├────────────────────────┼─────────────┼─────────────────────┼──────────────────────────────────────┼──────────────────────────────────────┼────────────┼─────────┼───────────┼───────────────────────┤
│ server-0 │ QueryStart │ 2023-04-26 06:25:52 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 1f810b3c-b3cb-4a7b-bc6c-8c8cc1e52515 │ 0.00 B │ 0 │ 0 │ 17604798521132779336 │
└────────────────────────┴─────────────┴─────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴────────────┴─────────┴───────────┴───────────────────────┘
└────────────────────────┴─────────────┴─────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴────────────┴─────────┴───────────┴───────────────────────┘

相反,query_id = initial_query_id 将只返回在第一个抛出分布式查询的本地节点上执行的查询

SELECT
hostname(),
type,
event_time,
initial_query_id,
query_id,
formatReadableSize(memory_usage) AS memory,
ProfileEvents.Values[indexOf(ProfileEvents.Names, 'UserTimeMicroseconds')] AS userCPU,
ProfileEvents.Values[indexOf(ProfileEvents.Names, 'SystemTimeMicroseconds')] AS systemCPU,
normalizedQueryHash(query) AS normalized_query_hash
FROM clusterAllReplicas(default, system.query_log)
WHERE (query_id = initial_query_id) AND (initial_query_id = 'a7262fa2-bd8b-4b51-a359-621ccf282417')
ORDER BY memory_usage DESC
LIMIT 10 FORMAT Pretty;

给出

┏━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ hostname() ┃ type ┃ event_time ┃ initial_query_id ┃ query_id ┃ memory ┃ userCPU ┃ systemCPU ┃ normalized_query_hash ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ server-2 │ QueryFinish │ 2023-04-26 06:25:53 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 123.08 MiB │ 1849115 │ 123412 │ 4258439895846105173 │
├────────────────────────┼─────────────┼─────────────────────┼──────────────────────────────────────┼──────────────────────────────────────┼────────────┼─────────┼───────────┼───────────────────────┤
│ server-2 │ QueryStart │ 2023-04-26 06:25:52 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ a7262fa2-bd8b-4b51-a359-621ccf282417 │ 0.00 B │ 0 │ 0 │ 4258439895846105173 │
└────────────────────────┴─────────────┴─────────────────────┴──────────────────────────────────────┴──────────────────────────────────────┴────────────┴─────────┴───────────┴───────────────────────┘

关于其他系统表,您可以在我们的 文档 中找到有关每个字段含义的更多详细信息。

·阅读时间:2 分钟

假设您创建一个使用 File 表引擎和 Parquet 格式的表

CREATE TABLE parquet_test
(
`x` UInt32,
`y` String
)
ENGINE = File(Parquet)

您可以向表格写入一次

INSERT INTO parquet_test VALUES
(1, 'Hello'),
(2, 'Hi')

这将在 data/default/parquet_test 文件夹中创建一个名为 data.Parquet 的文件。如果您尝试插入另一个批次

INSERT INTO parquet_test VALUES
(3, 'World'),
(4, 'Bye')

...您将收到以下错误

Code: 641. DB::Exception: Received from localhost:9000. DB::Exception: Cannot append data in format Parquet to file, because this format doesn't support appends. You can allow to create a new file on each insert by enabling setting engine_file_allow_create_multiple_files. (CANNOT_APPEND_TO_FILE)

您不能将数据追加到 ClickHouse 中的 Parquet 文件。但是,您可以通过启用 engine_file_allow_create_multiple_files 设置 来告诉 ClickHouse 为每次 INSERT 操作创建一个新文件。如果启用,每次插入都会创建一个新文件,其名称遵循以下模式

`data.Parquet` -> `data.1.Parquet` -> `data.2.Parquet`, etc.:

让我们试一试。我们将把这两个命令放在一个名为 parquet.sql 的文件中

SET engine_file_allow_create_multiple_files = 1;

INSERT INTO default.parquet_test VALUES (3, 'World'), (4, 'Bye');

使用 clickhouse-client 运行它

./clickhouse client --queries-file parquet.sql

现在您将在 data/default/parquet_test 中看到两个文件(以及每个后续插入的新文件)。

注意

engine_file_allow_create_multiple_files 设置适用于其他不可追加的数据格式,例如 JSON 和 ORC。

·阅读时间:2 分钟

问题:如何显示过去 60 分钟内涉及物化视图的所有查询?

回答

此查询将显示所有针对物化视图的查询,考虑到

  • 我们可以利用 system.tables 表中的 create_table_query 字段来识别哪些表是 MV 的显式(TO)接收者;
  • 我们可以使用(uuid 和名称约定 .inner_id.<uuid>)追溯哪些表是 MV 的隐式接收者;

我们还可以配置要回溯的时间长度,方法是更改初始查询 CTE 中的值(默认为 60 分钟)

WITH(60) -- default 60m
AS timeRange,
(
--prepare names of possible implicit MV hidden target tables for *any* table with NON NULL uuid
SELECT groupArray(
concat('default.`.inner_id.', toString(uuid), '`')
)
FROM clusterAllReplicas(default, system.tables)
WHERE notEmpty(uuid)
) AS MV_implicit_possible_hidden_target_tables_names_array,
(
--captures MV name and target tables (if TO is specified)
--TODO it seems that extract will return just the first capturing group :( replace with regexpExtract once available
SELECT arrayFilter(
x->x != '',
--remove empty captures
groupArray(
extract(
create_table_query,
'^CREATE MATERIALIZED VIEW\s(\w+\.\w+)\s(?:TO\s(\S+))?'
)
)
)
FROM clusterAllReplicas(default, system.tables)
WHERE engine = 'MaterializedView'
) AS MV_explicit_target_tables_names_array
SELECT event_time,
query,
tables as "MVs tables"
FROM clusterAllReplicas(default, system.query_log)
WHERE (
-- only SELECT within 60m
event_time > now() - toIntervalMinute(timeRange)
AND startsWith(query, 'SELECT')
) -- check either that query involves implicit MV target table names
AND (
hasAny(
tables,
MV_implicit_possible_hidden_target_tables_names_array
)
OR -- check that query involves explicit MV target table
hasAny(tables, MV_explicit_target_tables_names_array)
)
ORDER BY event_time DESC;

预期输出

| event_time          | query                                                                                          | MVs tables                                                            |
| ------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
| 2023-02-23 08:14:14 | SELECT rand(),* FROM default.sum_of_volumes, default.big_changes, system.users | ["default.big_changes_mv","default.sum_of_volumes_mv","system.users"] |
| 2023-02-23 08:04:47 | SELECT price,* FROM default.sum_of_volumes, default.big_changes | ["default.big_changes_mv","default.sum_of_volumes_mv"] |

在此示例中,上面的结果 default.big_changes_mvdefault.sum_of_volumes_mv 都是物化视图。