【问题标题】:Faster select when filtering with second or third sorted column使用第二个或第三个排序列进行过滤时选择更快
【发布时间】:2020-10-09 06:43:45
【问题描述】:

我们有一个时间序列表,定义如下

CREATE TABLE timeseries.mytable
(
    `ts` DateTime('UTC'),
    `src_ip` String,
    `dst_ip` String,
    `col_other` String
)
ENGINE = MergeTree()
PARTITION BY toDate(tr)
ORDER BY (dst_ip,ts,src_ip)
SETTINGS index_granularity = 8192

SELECT count(*) FROM timeseries.mytable;
# Elapsed 0.004 sec. Has 383M records


SELECT count(*) FROM timeseries.timeseries WHERE dst_ip = 'a.b.c.d';
# Elapsed: 0.085 sec.

SELECT count(*) FROM timeseries.timeseries WHERE src_ip = 'a.b.c.d';
# Elapsed: 53.031 sec

从上面可以看出,使用第一个排好序的列 (dst_ip) 过滤数据非常快。

如何更快地使用第三个排序列 (src_ip) 进行选择?

【问题讨论】:

    标签: clickhouse


    【解决方案1】:

    一些备注:

    • 第三个查询 (WHERE src_ip = 'a.b.c.d') 由于 未使用索引 而 CH 使用全扫描,因此运行缓慢。除了重新设计主键或者如果这个查询只计算聚合使用额外的AggregatingMergeTree-table

    • 您提供的用例看起来是人为的,因为 all 数据集计算行数并不是时间序列数据的关键用例。为什么结果不受dst_ipts限制?

    • 在需要计算聚合值时考虑使用ClickHouse AggregatingMergeTree Approach(在您的情况下为 count

    • 主键的设计需要理解,因为 CH 在查询优化中使用它(参见 Primary Keys and Indexes in QueriesMore secrets of ClickHouse Query Performance

    • 建议使用monotonic index

    • 要选择最佳索引,需要进行一系列测试以找到最适合具体用例的索引


    我会建议下一个主键:

    /* [pretty suspicious suggestion] Remove date-column (it makes much slower the all date range queries with a range less than Daily). */
    ORDER BY (dst_ip, src_ip)
    
    /* Define the granularity of date. Instead of toStartOfHour can be used any interval less than 'Daily' (where Daily is defined by partition key) */
    ORDER BY (dst_ip, toStartOfHour(ts), src_ip)
    
    /* Move the date to the first position (it makes faster queries with date range without dst_ip and get monotonic-index related advantages). */
    ORDER BY (toStartOfHour(ts), dst_ip, src_ip)
    

    对于每个主键需要选择更有效的索引粒度-值。

    【讨论】:

    • 唯一的方法是用另一个ORDER BY 将数据复制到第二个表并查询那个新表。
    • 谢谢@vladimir。用例是在给定的时间间隔内使用 src_ip 或 dst_ip 提取数据。聚合由下游数据管道完成。我会尝试建议的主键组合。
    【解决方案2】:

    欢迎来到 Stackoverflow。

    您应该尝试根据列的值基数在 ORDER BY 子句中保持不同的顺序进行测试。在这种情况下,可能会尝试按类将 src_ip 放在 ts 之前。

    在 MergeTree 引擎中,行是根据每个分区中的 ORDER BY 键排序的。

    之后,您可以根据您的应用程序将如何查询大多数项目的数据来决定 ORDER by 子句中列的最终排列。

    你可以找到类似的讨论here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-06
      • 2019-03-13
      • 2023-04-06
      • 2014-08-16
      • 1970-01-01
      相关资源
      最近更新 更多