【问题标题】:ClickHouse - SELECT row of data is too slowClickHouse - SELECT 行数据太慢
【发布时间】:2021-09-16 02:38:45
【问题描述】:

我们的项目中出现了以下问题,我们无法解决。 我们有大量的日志数据,我们从 MongoDB 转到 ClickHouse。

我们的表是这样创建的:

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 行 130000+ 的结果经过:7.994 秒

太慢了。

似乎 CH 处理了表中的所有行。哪里出了问题,需要提高 CH 的速度?

在 MongoDB 上相同的实现需要 200-500 毫秒 ma​​x

【问题讨论】:

  • 也许您可以尝试从 where select 中提取 raw,然后调用 JSONExtractString 获取您需要的参数

标签: sql mongodb performance clickhouse clickhouse-go


【解决方案1】:

叶戈尔!当您提到“我们从 MongoDB 转到 ClickHouse”时,您的意思是说您从 MongoDB 切换到 ClickHouse 来存储您的数据吗?或者您以某种方式从 MongoDB 连接到 ClickHouse 以运行您所指的查询?

我不确定您是如何提取数据的,但让我们专注于阅读部分。

对于 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 语句使用按月分区(即 toYYYYMM())。您可以通过查看system.parts 表来检查:

SELECT
    partition,
    name,
    active
FROM system.parts
WHERE table = 'logs'

所以,如果你想按周存储数据,我想分区可能是这样的

...
ORDER BY (device_id, ts)
PARTITION BY toMonday(week)

这也是一条好消息:Using Partitions and Primary keys in queries

【讨论】:

  • 酷,它的工作))谢谢!)这可能会解决我们的问题。
  • 有些查询变快了 200-500 毫秒,有些则慢了 1-2 秒。或多或少地采取分区是否有意义?
  • 要回答为什么某些查询需要 1-2 秒,您需要查看 CH 尝试读取多少部分才能满足查询。您可以尝试使用EXPLAIN 语法(在最近的版本中添加),或--send_logs_level=trace 与您联系时使用clickhouse client。但是,是的,主要是因为 CH 必须接触磁盘上的更多部分。
猜你喜欢
  • 2021-10-09
  • 1970-01-01
  • 2020-07-15
  • 1970-01-01
  • 1970-01-01
  • 2017-10-19
  • 1970-01-01
  • 2021-12-11
  • 2023-03-25
相关资源
最近更新 更多