以下问题发生在我们的项目中,我们无法解决。我们有大量的日志数据,我们从MongoDB转到MongoDB。
我们的表是这样创建的:
CREATE TABLE IF NOT EXISTS logs ON CLUSTER default (
raw String,
ts DateTime64(6) MATERIALIZED toDateTime64(JSONExtractString(raw, 'date_time'), 6),
device_id String MATERIALIZED JSONExtractString(raw, 'device_id'),
level Int8 MATERIALIZED JSONExtractInt(raw, 'level'),
context String MATERIALIZED JSONExtractString(raw, 'context'),
event String MATERIALIZED JSONExtractString(raw, 'event'),
event_code String MATERIALIZED JSONExtractInt(raw, 'event_code'),
data String MATERIALIZED JSONExtractRaw(raw, 'data'),
date Date DEFAULT toDate(ts),
week Date DEFAULT toMonday(ts)
)
ENGINE ReplicatedReplacingMergeTree()
ORDER BY (device_id, ts)
PARTITION BY week
我正在运行这样的查询
SELECT device_id,toDateTime(ts),context,level,event,data
FROM logs
WHERE device_id = 'some_uuid'
ORDER BY ts DESC
LIMIT 10
OFFSET 0;
这是一组10行的结果。运行:6.23秒.
第二,没有命令,限制和抵消:
SELECT device_id,toDateTime(ts),context,level,event,data
FROM logs
WHERE device_id = 'some_uuid'
这是经过的结果:每500行的为7.994秒。
太慢了。
似乎CH处理了表中的所有行。有什么不对,有什么需要提高CH的速度?
在MongoDB上的相同实现需要200-500 on max。
发布于 2021-07-05 13:03:24
伊戈尔!当您提到“我们从ClickHouse到MongoDB”时,您的意思是从MongoDB切换到ClickHouse来存储数据吗?或者您以某种方式从ClickHouse连接到MongoDB来运行您所指的查询?
我不知道你是如何吸收你的数据的,但是让我们集中在阅读部分。
对于MergeTree家族,ClickHouse以部分方式写入数据。因此,将时间戳作为where子句的一部分至关重要,因此ClickHouse可以确定要读取的部分,并跳过大多数不需要的数据。否则,它将扫描所有数据。
我可以想象这些查询会更快地完成扫描:
SELECT device_id,toDateTime(ts),context,level,event,data
FROM logs
WHERE device_id = 'some_uuid' AND week = '2021-07-05'
ORDER BY ts DESC
LIMIT 10
OFFSET 0;
SELECT device_id,toDateTime(ts),context,level,event,data
FROM logs
WHERE device_id = 'some_uuid' AND week = '2021-07-05';
AFAIK,除非您指定了确切的分区格式,否则CH将对您的CREATE TABLE
语句使用按月分区(即CREATE TABLE
)。您可以通过查看system.parts
表来检查该表:
SELECT
partition,
name,
active
FROM system.parts
WHERE table = 'logs'
因此,如果您想将数据存储在每周的部分中,我可以想象分区可能就像
...
ORDER BY (device_id, ts)
PARTITION BY toMonday(week)
这也是一个很好的信息:在查询中使用分区和主键
https://stackoverflow.com/questions/68254023
复制相似问题