如何在clickhouse的主键中使用“toyyyymmdd(timestamp)”

xoshrz7s  于 2021-07-15  发布在  ClickHouse
关注(0)|答案(1)|浏览(1681)

我使用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-4000万行)进行测试。
当我使用 TimeStamp 过滤条件,我得到一些混乱的结果。以下是我的sql:

select count(*) from MyTable WHERE 
TimeStamp>=toDateTime('2019-01-30 00:00:00') 
and 
TimeStamp<toDateTime('2019-02-04 00:00:00')

它处理了7562万行(1月和2月的全部数据)!这意味着查询条件可以命中正确的分区,但缺少主键。但是如果手动转换时间戳,如下所示:

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可以在没有转换时间戳的情况下命中正确的分区,为什么它也不能自动命中主键呢?我真的需要手动转换时间戳吗?

4xrmg8kj

4xrmg8kj1#

表定义将过多的信息添加到用于将索引定义到行数据的顺序中。我猜,当您将筛选条件指定为todatetime('2019-01-30 00:00:00')时,clickhouse不能使用索引的第一部分。结果,它读了整个部分。请尝试按以下方式定义表:

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)

在这种情况下,两个查询的性能应该相同。在这两种情况下,它可能比过滤器与索引的第一列完全匹配的最快查询慢一点,但比不匹配的查询快一点。
有关正在进行的操作的更多信息,请查看clickhouse日志,它位于/var/log/clickhouse-server/clickhouse-server.log中。您将看到一些消息,告诉您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

在这种情况下,我们可以看到它选择了相对较少的标记(即数据颗粒)来读取。这使您了解主键索引的工作效率。

相关问题