查询计划 ---------- 查询计划是为了得到一个查询的结果所需的数据库操作集合,操作可以是scan,aggregation,join等,这些操作形成一棵树状结构,树的每一个节点是一个操作。在查询计划执行过程中,子节点的输出以流水线的形式传递到父节点。 除了常见的数据库操作外(比如 scan,join 等),为了支持查询的并行执行,OushuDB 添加了 motion 操作。motion 操作主要实现查询执行过程中元组在节点之间的传递。OushuDB 现在支持三种 motion 操作: * redistribute motion: 按照hash值把数据发送到多个目标节点。 * broadcast motion: 把数据广播到所有目标节点。 * gather: 把数据从多个节点收集到一个节点。 查询计划例子 ++++++++++++ 下面给出一个查询计划的例子,本例中涉及两张表,lineitem和orders。其中lineitem表较大,orders表较小。lineitem表按照l_orderkey hash分布,而orders表随机分布。 .. code-block:: html :linenos: SELECT l_orderkey, count(l_quantity) FROM lineitem, orders WHERE l_orderkey = o_orderkey GROUP BY l_orderkey; 上面SQL语句会产生如下图所示的查询计划。查询计划的执行是自底向上的。该查询计划表示先对orders表按照o_orderkey重新分布,然后和表lineitem做hash join,然后再做aggregation,最后结果会通过gather motion收集起来。 .. image:: ../_static/userguide-query-plan.png 图1. 查询计划 下面是explain的输出,和上图一样,只是不同的表示形式。 .. code-block:: html :linenos: QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Gather Motion 2:1 (slice2; segments: 2) (cost=291565.56..318376.51 rows=1220947 width=16) -> HashAggregate (cost=291565.56..318376.51 rows=610474 width=16) Group By: lineitem.l_orderkey -> Hash Join (cost=70069.00..250010.38 rows=3000608 width=15) Hash Cond: lineitem.l_orderkey = orders.o_orderkey -> Append-only Scan on lineitem (cost=0.00..89923.15 rows=3000608 width=15) -> Hash (cost=51319.00..51319.00 rows=750000 width=8) -> Redistribute Motion 2:2 (slice1; segments: 2) (cost=0.00..51319.00 rows=750000 width=8) Hash Key: orders.o_orderkey -> Append-only Scan on orders (cost=0.00..21319.00 rows=750000 width=8) 针对每一个操作,explain语句都会输出几方面信息: * cost: cost为1.0表示等价于一个顺序磁盘页读的代价。第一个cost值为start-up代价,指的是从该操作开始执行到输出第一行的代价估计值。第二个cost值为得到所有行的代价估计值。 * rows:该计划节点估计输出行数,此处的行数估计是每一个virtual segment输出行数的估计值。 * width:该计划节点输出元组的近似宽度。 针对某些类别节点,explain语句还会输出其他信息,比如HashAggregate的聚集key等。