【问题标题】:Clickhouse - query performance degradationClickhouse - 查询性能下降
【发布时间】:2020-05-19 13:12:18
【问题描述】:

我有一个运行速度非常快(1-2 秒)并返回 20 行的简单查询:

select * from table where field1 = 'ABC'

但是,如果我在另一个字段上再添加一个过滤器,例如:

select * from table where field1 = 'ABC' and field2 = 'XYZ'

查询超时(我们有 30 秒的限制)。如果重要的话,在我们的例子中,查询应该返回相同的 20 行。

这两个字段都不是排序键的一部分,并且该表包含大约 2.5 亿行和大约 20 列。

问题是:这是预期的行为吗?我希望查询运行时间应该或多或少相等。如果符合预期,是否有指南应该避免什么样的查询,或者是否有工具可以调查它是否是“坏”查询。

提前致谢!

【问题讨论】:

  • 第二次查询需要更长的时间是很自然的,因为会有更多的比较,但我无法弄清楚它如何花费超过 30 秒。你说的超时是什么意思?您是从 clickhouse-client 还是 JDBC 发送查询?
  • 你能透露一下这两列的类型吗?我怀疑 select * from table where field2 = 'XYZ' 也需要很长时间 - 你能检查一下吗?
  • 你可以试试这个:select * from (select * from table where field1 = 'ABC') where field2 = 'XYZ' settings enable_optimize_predicate_expression=0;
  • 谢谢大家! 1) 只是通过 REST 2) 是的,确实如此。 3) 工作速度快。我猜丹尼斯已经详细说明了,现在一切似乎都清楚了。

标签: clickhouse


【解决方案1】:

是的。这是预期的。在某些情况下,CH 会为 prewhere 选择错误的列,因为它没有统计信息并且使用基于规则的算法。

试试

select * from table 
prewhere field1 = 'ABC' 
where field2 = 'XYZ'

【讨论】:

  • 您的回答总是很棒,我需要收集所有这些并提出“最佳点击屋提示”。
  • 谢谢,丹尼斯!现在事情有点清楚了。但我认为无论如何都会在大多数行被过滤掉的情况下发生全表扫描。为什么会有所作为。您还提到了基于规则的算法。如果 CH 没有统计数据,那么还考虑了哪些其他变量?
  • @Vyacheslav CH 使用一些列(轻量级 - 小)来做 prewhere(第一次过滤)。因此 CH 使用 PrimaryKey 过滤器(在这种情况下不是)读取 prewhere field1 = 'ABC' field1 列并收集合适的标记(指向 = 'ABC' 的颗粒的指针)。在第二阶段,CH 使用收集的标记和过滤器 = 'XYZ' 读取所有其他列(在本例中为 *)。在 optimize_move_to_prewhere 算法选择最小(以字节为单位)列的情况下——例如 field2 的问题,这个条件 field2 = 'XYZ' 可能对所有行都为真,而 CH 在 PREWHERE 阶段没有过滤掉任何内容
  • 顺便说一句,prewhere field1 = 'ABC' and field2 = 'XYZ' 可能会更好
  • 非常感谢您的解释!
猜你喜欢
  • 2014-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-21
  • 1970-01-01
相关资源
最近更新 更多