Join 交叉联接中表的顺序如何影响性能

Join 交叉联接中表的顺序如何影响性能,join,clickhouse,Join,Clickhouse,我有两个表A和B,它们都是合并树,索引粒度为8192。 当我对两个表应用交叉连接时。一般来说,查询喜欢 select count(*) from (select * from A where ... ) cross join (select * from B where ...) where ...; 原始表:A有314307856条记录,B有909470条记录。 过滤掉:A有6599条记录,B有14860条记录。两个过滤器都非常快,尽管记录有显著差异 在查询中切换a和B的顺序时,我注

我有两个表A和B,它们都是合并树,索引粒度为8192。 当我对两个表应用交叉连接时。一般来说,查询喜欢

select
    count(*)
from
(select * from A where ... )
cross join
(select * from B where ...)
where ...;
原始表:A有314307856条记录,B有909470条记录。 过滤掉:A有6599条记录,B有14860条记录。两个过滤器都非常快,尽管记录有显著差异 在查询中切换a和B的顺序时,我注意到性能上的巨大差距

当交叉连接B时:集合中有1行。时间:12.242秒。处理了2672万行

当B交叉连接A时:集合中有1行。时间:45.584秒。处理了2672万行

两个订单都有管道

有时,B交叉连接A

->我注意到clickhouse服务器将使用此管道快速释放我的内存

正如我所知,使用joinquery,clickhouse将首先执行右侧的执行,然后将其放入内存,然后执行左侧的执行。在我的例子中,过滤掉的A和B都绝对适合内存

我的问题是:

为什么两个查询的性能有巨大的差异?两个表的顺序如何影响查询性能?选择订单时的一些建议

在多次执行中,同一查询的管道是否可以不同

更新1: 有关我的查询的更多详细信息

SELECT 
    count(*)
    FROM 
    (
          SELECT 
            ...
        FROM B 
        WHERE (((day >= '2018-08-15') AND (day <= '2018-08-16')) AND ((timestamp >= 1534310226442) AND (timestamp <= 1534399065648))) AND (log_time <= 1534316318187)
    ) 
    CROSS JOIN 
    (
      SELECT 
            ...
        FROM A
        WHERE (((day >= '2018-08-14') AND (day <= '2018-08-16')) AND ((timestamp >= 1534223826442) AND (timestamp <= 1534399065648))) AND (log_time <= 1534316318187) AND match(..., '...') 
    ) 
    WHERE position(..., ...) > 1
目前,ClickHouse没有基于成本的优化器来自动交换表,如果这是实现相同结果的更有利的方式。首先,存在这种差异的原因可能有很多,比如更好的处理器缓存利用率,或者因为位置的原因在丢弃之前做额外的工作。性能内省功能目前正在合并到ClickHouse master中,并将在即将发布的版本中提供,因为现在深入挖掘主要局限于普通的linux工具集,如perf/strace/dstat/等。根据建议,您做了完全正确的事情,测量了什么最适合您的情况,不要盲目相信任何人的建议。 ClickHouse或多或少是确定性的,所以它不应该随着固定查询而改变。你能提供一种复制的方法吗?
请告诉我们WHERE子句在做什么,因为您可能不是真正在做交叉连接。嗨。首先阅读关系数据库教科书中的查询优化/实现章节。请阅读并采取行动。
CreatingSets
 Lazy
 Expression
  Expression
   Aggregating
    Concat
     Expression
      Filter
       Expression
        Limit
         Expression
          Union
           Limit × 7
            Expression
             Filter
              MergeTreeThread
SELECT 
    count(*)
    FROM 
    (
          SELECT 
            ...
        FROM B 
        WHERE (((day >= '2018-08-15') AND (day <= '2018-08-16')) AND ((timestamp >= 1534310226442) AND (timestamp <= 1534399065648))) AND (log_time <= 1534316318187)
    ) 
    CROSS JOIN 
    (
      SELECT 
            ...
        FROM A
        WHERE (((day >= '2018-08-14') AND (day <= '2018-08-16')) AND ((timestamp >= 1534223826442) AND (timestamp <= 1534399065648))) AND (log_time <= 1534316318187) AND match(..., '...') 
    ) 
    WHERE position(..., ...) > 1