首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在clickhouse主键中使用“`toYYYYMMDD(时间戳)”

如何在clickhouse主键中使用“`toYYYYMMDD(时间戳)”
EN

Stack Overflow用户
提问于 2019-08-28 08:47:19
回答 1查看 5.2K关注 0票数 1

我使用clickhouse作为我的项目基础数据库和它的MergeTree表工程。我尝试使用Custom Partitioning Key特性,并创建了如下表:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
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,如下所示:

代码语言:javascript
运行
复制
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吗?

EN

回答 1

Stack Overflow用户

发布于 2019-08-29 22:08:46

表定义将过多的信息添加到用于将索引定义到行数据的顺序中。当您将筛选条件指定为ClickHouse (‘2019-01-3000:00:00“)时,我猜想toDateTime不能使用索引的第一部分。因此,它最终阅读了整个部分。尝试按以下方式定义您的表:

代码语言:javascript
运行
复制
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实际读取了多少数据来进行计数。下面是一个例子。

代码语言:javascript
运行
复制
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

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57688401

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档