我使用clickhouse作为我的项目基础数据库和它的MergeTree
表工程。我尝试使用Custom Partitioning Key
特性,并创建了如下表:
CREATE TABLE MyTable
(
UserID UUID,
ResourceID UUID,
TimeStamp DateTime,
Usage Int64,
Version UInt32
)
ENGINE = ReplacingMergeTree(Version)
PARTITION BY toYYYYMM(TimeStamp)
ORDER BY (toYYYYMMDD(TimeStamp), UserID, ResourceID , TimeStamp)
分区键是toYYYYMM(TimeStamp)
,这意味着clickhouse按月分隔数据。同时,我在主索引中使用toYYYYMMDD(TimeStamp)
作为第一列。我吃了一年的数据(大约每月3000万行)进行测试。
当我使用TimeStamp
筛选条件查询数据时,我得到了一些令人困惑的results.Here:
select count(*) from MyTable WHERE
TimeStamp>=toDateTime('2019-01-30 00:00:00')
and
TimeStamp<toDateTime('2019-02-04 00:00:00')
它处理了7,562万行(1月和2月的全部数据)!这意味着查询条件可以命中正确的分区,但遗漏了主键。但是,如果手动转换TimeStamp,如下所示:
select count(*) from MyTable WHERE
toYYYYMMDD(TimeStamp)>=toYYYYMMDD(toDateTime('2019-01-30 00:00:00'))
and
toYYYYMMDD(TimeStamp)<toYYYYMMDD(toDateTime('2019-02-04 00:00:00'))
然后,它只处理700万行(5-6天的数据)。这意味着查询条件按下主键。
使我感到困惑的是,既然clickhouse可以在不转换TimeStamp的情况下访问正确的分区,那么为什么它也不能自动地按主键呢?我真的需要手动转换TimeStamp吗?
发布于 2019-08-29 22:08:46
表定义将过多的信息添加到用于将索引定义到行数据的顺序中。当您将筛选条件指定为ClickHouse (‘2019-01-3000:00:00“)时,我猜想toDateTime不能使用索引的第一部分。因此,它最终阅读了整个部分。尝试按以下方式定义您的表:
CREATE TABLE MyTable (
UserID UUID,
ResourceID UUID,
TimeStamp DateTime,
Usage Int64,
Version UInt32 )
ENGINE = ReplacingMergeTree(Version)
PARTITION BY toYYYYMM(TimeStamp)
ORDER BY (UserID, ResourceID ,TimeStamp)
在这种情况下,您应该看到两个查询的性能相同。在这两种情况下,它可能都比最快的查询要慢一些,因为过滤器与索引的第一列完全匹配,但比不匹配的情况要快得多。
有关正在发生的事情的更多信息,请查看位于/var/log/clickhouse-server/clickhouse-server.log.中的ClickHouse日志您将看到一些消息,这些消息告诉您ClickHouse实际读取了多少数据来进行计数。下面是一个例子。
2019.08.29 14:46:39.507239 [ 41 ] {fc8cb747-5db2-40ac-afeb-32b61192de9a} <Debug> executeQuery: (from 127.0.0.1:49598) SELECT count(*) FROM MyTable WHERE (TimeStamp >= toDateTime('2019-09-30 00:00:00')) AND (TimeStamp < toDateTime('2019-10-04 00:00:00'))
...
2019.08.29 14:46:39.518160 [ 41 ] {fc8cb747-5db2-40ac-afeb-32b61192de9a} <Debug> default.MyTable (SelectExecutor): Selected 2 parts by date, 2 parts by key, 63 marks to read from 11 ranges
2019.08.29 14:46:39.518739 [ 41 ] {fc8cb747-5db2-40ac-afeb-32b61192de9a} <Trace> default.MyTable (SelectExecutor): Reading approx. 516096 rows with 2 streams
在这种情况下,我们可以看到,它选择了相对较少的标记(即数据颗粒)来读取。这让您了解主键索引的工作效率。
https://stackoverflow.com/questions/57688401
复制相似问题