java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2170|回复: 0

《大规模分布式存储系统》第10章 数据库功能【10.2】

[复制链接]
  • TA的每日心情
    开心
    2021-5-25 00:00
  • 签到天数: 1917 天

    [LV.Master]出神入化

    2025

    主题

    3683

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66101

    宣传达人突出贡献优秀版主荣誉管理论坛元老

    发表于 2017-3-10 13:47:36 | 显示全部楼层 |阅读模式
    10.2 只读事务
    , W, D1 [; X. `2 |9 V/ f只读事务(SELECT语句),经过词法分析、语法分析,预处理后,转化为逻辑! j0 \) l8 i' k; p
    查询计划和物理查询计划。以SQL语句select c1,c2 from t1 where id=1 group by c1
    ; ?5 J8 p5 ~! Korder by c2为例,MergeServer收到该语句后将调用ObSql类的静态方法
    # z: \8 H. t1 _, w0 i$ [: xdirect_execute,执行步骤如下:
    ! B6 k; }; j! O% `1)调用flex、bison解析SQL语句生成一个语法树。) h- M- C& d2 H
    2)解析语法树,生成逻辑执行计划ObSelectStmt。ObSelectStmt结构中记录了& @% g6 a9 ^1 V( a( X: v% z2 V1 S
    SQL语句扫描的表格名(t1),投影列(c1,c2),过滤条件(id=1),分组列
    2 {& ^# `: p6 z1 a(c1)以及排序列(c2)。, Y/ J. U+ J) M- N
    3)根据逻辑执行计划生成物理执行计划。ObSelectStmt只是表达了一种意图,+ T, C& h* \* ~1 m! W0 y% S, @& I
    但并不知道实际如何执行,ObTransformer类的generate_physical_plan将ObSelectStmt转
    ( ~  w4 `. a" E( P; E. o化为物理执行计划。7 n( x5 q+ l7 N3 J: e6 P
    逻辑查询计划的改进以及物理查询计划的选择,即查询优化器,是关系数据库
    ! R$ K: k1 M0 P" M- @3 C, @! K最难的部分,OceanBase目前在这一部分的工作不多。因此,本节不会涉及太多关于
    # y2 {3 _+ c7 P3 [如何生成物理查询计划的内容,下面仅以两个例子说明OceanBase的物理查询计划。1 n. V% q$ B7 F4 H3 k2 {# g
    例10-1 假设有一个单表SQL语句如图10-2所示。4 e$ p6 `/ r2 h  i
    图 10-2 单表物理查询计划示例
    + {, S9 g- |% o5 J. U单表SQL语句执行过程如下:
    ; |3 C) ~$ x, b1)调用TableScan操作符,读取子表t1中的数据,该操作符还将执行投影
    4 u( q* U! y! P3 N(Project)和过滤(Filter),返回的结果只包含c3=10的数据行,且每行只包含c1、
    1 p. R- s" v" A3 @c2、c3三列。
    : ^4 u1 r6 g* C2)调用HashGroupBy操作符(假设采用基于哈希的分组算法),按照c1对数据
    ; {6 w1 b6 ]8 M6 }7 l0 t分组,同时计算每个分组内c2列的总和。) j7 Q. p8 c+ d# P' x# l
    3)调用Filter操作符,过滤分组后生成的结果,只返回上一层sum(c2)>=10的( y$ O' f; r# C; x* n$ T, U
    行。% \6 _) F  Z, o, D8 p% z' ~- B  y
    4)调用Sort操作符将结果按照c1排序。* w3 V9 v  P2 `3 Z3 }' C: M& U8 e
    5)调用Project操作符,只返回c1和sum(c2)这两列数据。
    # f$ b6 ?8 U- _% C* ~6)调用Limit操作符执行分页操作,只返回前20条数据。7 w. C9 n: B) O
    例10-2 假设有一个需要联表的SQL语句如图10-3所示。
    - |; C& F! Y4 q: p' ~' R图 10-3 多表物理查询计划示例! i3 f! d# |' u3 w
    多表SQL语句执行过程如下:) z7 O5 p. K+ B
    1)调用TableScan分别读取t1和t2的数据。对于t1,使用条件c3=10对结果进行过
    / {% B; _( W2 D, G9 ^, D: N滤,t1和t2都只需要返回c1,c2,c3这三列数据。
    & e+ I: e. @; F4 R. [2)假设采用基于排序的表连接算法,t1和t2分别按照t1.c2和t2.c2排序后,调用
    8 c/ W1 R. g4 Y7 D; Y: C9 jMerge Join运算符,以t1.c2=t2.c2为条件执行等值连接。
    + f: |' W8 H4 \. @6 I- B; [  r3)调用HashGroupBy运算符(假设采用基于哈希的分组算法),按照t1.c1对数
    ! v& [5 K6 g# E& I# N9 j! E  z. k据分组,同时计算每个分组内t2.c3列的总和。: r! w5 l) I! `2 b8 R; h& o0 @& j: u6 }
    4)调用Filter运算符,过滤分组后的生成的结果,只返回上一层sum(t2.c3)>
    5 A7 J" d0 w9 M& f" z/ y0 w=10的行。+ @5 Y; {2 y+ ?) i
    5)调用Sort操作符将结果按照t1.c1排序。* U3 q7 F* X0 o+ u6 e: J8 H
    6)调用Project操作符,只返回t1.c1和sum(t2.c3)这两列数据。& e5 b' K- W( Z
    7)调用Limit操作符执行分页操作,只返回前20条数据。
    ) N- e3 I0 }) h10.2.1 物理操作符接口
    2 @3 \- t" @+ x3 e9.4.2节介绍一期分布式存储引擎中的迭代器接口为ObIterator,通过它,可以将0 Q5 A/ K3 A/ B8 x: x
    读到的数据以cell为单位逐个迭代出来。然而,数据库操作总是以行为单位的,因
    % ^1 i' ~3 d; g; l8 S) O& ?7 ]此,二期实现数据库功能层时考虑将基于cell的迭代器修改为基于行的迭代器。6 e! {# |1 Y6 w1 d
    行迭代器接口如下:0 s2 ~. ?/ F+ w+ _
    //ObRow表示一行数据内容" M' `. h  O; T3 F" D
    class ObRow7 r& v7 l; m" L4 s6 \
    {
    ' Q( _* p( y$ L6 m" Gpublic:
    ! O% V5 B7 A1 ]9 |//根据表ID以及列ID获得指定cell
    , e' N! i+ B7 a7 C8 p; `2 e//@param[in]table_id表格ID! r& q7 t1 C# l! Z9 T+ A* ]
    //@param[in]column_id列ID" q6 `7 u- f. u  m! q
    //@param[out]cell读到的cell; f$ U+ i- T( p; ]$ N2 G
    int get_cell(const uint64_t table_id,const uint64_t column_id,ObObj*&cell);
    % z' _6 n# Q; R& j//获取第cell_idx个cell
    & \. K! B! {/ w: p8 u5 g8 }int raw_get_cell(const int64_t cell_idx,const ObObj*&cell,uint64_t&table_id,
    / |4 s4 Z/ |+ U8 N" I* g+ buint64_t&column_id);
    & o! {$ l: H* x. y//获取本行的列数
    $ x9 o# |$ b; F, t" f* @5 [int64_t get_column_num()const;
    8 Z" N# O. i$ d- G% W};
    ; P4 l8 r' F$ F7 t# P7 \7 p6 H每一行数据(ObRow)包括多个列,每个列的内容包括所在的表: S% h* i/ p% t4 H" ^' N
    ID(table_id),列ID(column_id)以及列内容(cell)。ObRow提供两种访问方
    + i; s9 `# u& v' H9 ?0 X; n7 _式:根据table_id和column_id随机访问某个列,以及根据列下标(cell_idx)获取某个  G. V. |; [6 _" P" q- u" G" T; Y" o
    指定列。  g4 B9 D4 x/ }6 t$ p
    物理运算符接口如下:: B6 w" R4 S7 x8 q( y$ J9 i& E
    //物理运算符接口
    % x# g. p, S- L, P5 i) f  e' uclass ObPhyOperator$ F! \( z, I2 |) f7 _
    {
    % `" E7 [! ?; F* l( apublic:0 J9 N0 Y* B4 t8 M6 T+ k, w
    //添加子运算符,所有非叶子节点物理运算符都需要调用该接口
      s3 X) n+ _. S* y( j+ avirtual int set_child(int32_t child_idx,ObPhyOperator&child_operator);
    - ~* M8 X& `7 I0 H& D//打开物理运算符。申请资源,打开子运算符等1 ]  H2 z* H7 h! b1 q+ \2 P6 O- d$ s
    virtual int open()=0;
    ' l7 C0 i6 w" w/ l3 N3 U; a6 [//关闭物理运算符。释放资源,关闭子运算符等/ U# x- }1 A, m+ p$ X% b, ~
    virtual int close()=0;
    , |# V+ f+ n- \' ]//获得下一行数据内容  {# d2 i; X& x5 l! G
    //@param[out]row下一行数据内容的引用( E* w( P, [9 z! A  R0 l
    //@return返回码,包括成功、迭代过程中出现错误以及迭代完成
    9 A, V$ T3 n7 y% ?7 L2 jvirtual int get_next_row(const ObRow*&row)=0;
    - q9 O: }$ ?9 a6 D* o};5 d+ s7 ~: K9 Z
    ObPhyOperator每次获取一行数据,使用方法如下:& y  X& L  o) g
    ObPhyOperator root_operator=root_operator_;//根运算符4 `5 b3 H' t; }( h1 N
    root_operator->open();
    5 V" H0 y' o; h# }# h* a- o6 XObRow*row=NULL;2 x- k1 r& g: d, U
    while(OB_SUCCESS==root_operator->get_next_row(row))% W  y% \; h: h1 V" p- q& p- _" m3 L+ h
    {& l$ ?" H& u  A/ ]
    Output(row);//输出本行
    , K/ C' ^* o/ G' u! z! ?}
    ( @" r1 ^1 R% L' n) D* Z* _9 ^. v8 Lroot_operator->close();
    6 l: C) K- j3 ^; u8 J# y5 `6 X为什么ObPhyOperator类中有一个set_child接口呢?这是因为所有的物理运算符构. W' k. b" A0 `6 Z
    成一个树,每个物理运算的输出结果都可以认为是一个临时的二维表,树中孩子节6 E" f4 k( f! k) N& \
    点的输出总是作为它的父亲节点的输入。例10-1中,叶子节点为一个TableScan类型
    ' y& B. ^! r. D/ [! y6 C9 {的物理运算符(称为table_scan_op),它的父亲节点为一个HashGroupBy类型的物理: G! a/ I0 W4 u0 r% n5 V9 r
    运算符(称为hash_group_by_op),接下来依次为Filter类型物理运算符filter_op,Sort
    7 T! }7 u" \( p/ E) x; ^类型物理运算符sort_op,Project类型物理运算符project_op,Limit类型物理运算符) `& _- v1 X" Q. V8 J' ]6 f
    limit_op。其中,limit_op为根运算符。那么,生成物理运算符时将执行如下语句:
    ) Q7 G6 \: C9 _3 p) {2 W1 R% _4 Glimit_op->set_child(0,project_op);" I, r/ m' S4 D; s. F2 N0 \
    project_op->set_child(0,sort_op);/ d( i; F) Y& p  t$ O: ^8 M
    sort_op->set_child(0,filter_op);4 w+ E! X) u$ O' X8 k- G0 @
    filter_op->set_child(0,hash_group_by_op);
    $ ]/ O) e. L+ g1 T7 xhash_group_by_op->set_child(0,table_scan_op);0 c+ B, Z2 _6 o7 O2 R
    root_op=limit_op;+ E+ J; V  Z  L+ Y" S; b
    SQL最终执行时,只需要迭代root_op(即limit_op)就能够把需要的数据依次迭: H) |1 c" ?1 z9 A/ A' c
    代出来。limit_op发现前一批数据迭代完成则驱动下层的project_op获取下一批数据,
    # B3 T5 F# Z- K- c" @project_op发现前一批数据迭代完成则驱动下层的sort_op获取下一批数据。以此类
    - y5 _/ G0 b+ R推,直到最底层的table_scan_op不断地从原始表t1中读取数据。" \' o4 j' \8 j7 ?; w" i4 ?  \: q  Q! M
    10.2.2 单表操作
    ! q7 m$ ?3 Y9 r单表相关的物理运算符包括:
    " S3 [8 E+ E. {- O●TableScan:扫描某个表格,MergeServer将扫描请求发给请求的各个子表所在3 N3 a' w4 ?) H- e4 U- U: P6 ]
    的ChunkServer,并将ChunkServer返回的结果按照子表范围拼接起来作为输出。如果
    " |# h! t* T7 M: Z5 W  k+ Z# O请求涉及多个子表,TabletScan可由多台ChunkServer并发执行。
    1 W/ a2 D6 T5 c0 N; `/ c5 }% [●Filter:针对每行数据,判断是否满足过滤条件。
    3 b. h/ X) ]: K5 V8 n●Projection:对输入的每一行,根据定义的输出表达式,计算输出结果行。* n+ A/ j" y7 v  V- F% Y2 F* V2 p
    ●GroupBy:把输入数据按照指定列进行聚集,对聚集后的每组数据可以执行计9 d+ _/ l6 O2 \/ ?0 F
    数(count)、求和(sum)、计算最小值(min)、计算最大值(max)、计算平均值
    : K5 C$ R. L" L& `( X(avg)等聚集操作。
    " X! T! A( H1 }. v- I4 \& P! a●Sort:对输入数据进行整体排序,如果内存不够,需要使用外排序。2 K7 X  X* J  o) L' N
    ●Limit(offset,count):返回行号在[offset,offset+count)范围内的行。
    " J4 C2 `! w  @3 f$ F& f●Distinct:消除某些列相同的重复行。
    - p8 e( t! Z% W$ b* a$ x$ YGroupBy、Distinct物理操作符可以通过基于排序的算法实现,也可以通过基于哈
    $ ]8 ~: Z! X/ a5 G. n! P6 A希的算法实现,分别对应HashGroupBy和MergeGroupBy,以及HashDistinct和
    * U3 g& }+ {* S3 iMergeDistinct。下面分别讨论排序算法和哈希算法。
    / S7 C0 [: m, v4 H- m- X8 ]/ {: P1.排序算法
    + {& Q5 C: @' H5 p: K7 WMergeGroupBy、MergeDistinct以及Sort都需要使用排序算法。通用的<key,value
    0 P& R5 b/ f, \+ j( g4 s5 o4 q>排序器可以分为两个阶段:; }/ F2 N( c0 Y- ^, J- `
    ●数据收集:在数据收集阶段,调用者将<key,value>对依次加入到排序器。如! Z! m# t# O- Z1 Q
    果数据总量超过排序器的内存上限,需要首先将内存中的数据排好序,并存储到外) C5 B1 @2 E8 ?5 Z, g7 ]# A
    部磁盘中。
    : [. I% I* b+ T) s5 s& ~●迭代输出:迭代第一行数据时,内存中可能有一部分未排序的数据,磁盘中也" m" p) G1 ~9 t$ ~8 Q
    可能有几路已经排好序的数据。因此,首先将内存中的数据排好序。如果数据总量
    & C0 Y' x: t% ^3 }( x不超过排序器内存上限,那么将内存中已经排好序的数据按行迭代输出(内排
    8 l7 J2 S3 y( q# g% d% B序);否则,对内存和磁盘中的部分有序数据执行多路归并,一边归并一边将结果& x  ]1 V& C, K; ~" W: V; V
    迭代输出。7 y+ J& x7 A+ ~
    2.哈希算法$ p; R- H5 a0 W$ |
    HashGroupBy以及HashDistinct都需要使用哈希算法。假设需要对<key,value>对
    * f/ I( A$ C* v- @2 `+ K2 I按照key分组,那么首先使用key计算哈希值K,并将这个<key,value>对写入到第K个% e( i7 |9 |) j$ N; }. G- R0 P, b
    桶中。不同的key可能对应相同的哈希桶,因此,还需要对每个哈希桶内的<. o* K* _: H9 v% J9 V0 C, \
    key,value>对排序,这样才能使得key相同的元组能够连续迭代出来。哈希算法的难
    * |$ O& E1 f0 T! A' b2 ^点在于数据总量超过内存上限的处理,由于篇幅有限,请自行思考。6 t: C0 j) d+ o
    10.2.3 多表操作$ c- S. b; N! h6 K
    多表相关的物理操作符主要是Join。最为常见的Join类型包括两种:内连接
    ) ?, N4 ~& t" {) f" L+ j  g$ _* L(Inner Join)和左外连接(Left Outer Join),而且基本都是等值连接。如果需要连接) f. O; }& X: W5 G& \7 J
    多张表,可以先连接前两张表,再将前两张表连接生成的结果(相当于一张临时
    : X) k: @9 G* A, ], J6 b, c) I表)与第三张表格连接,以此类推。8 {, V" J8 H0 H$ b3 A
    两张表实现等值连接方式主要分为两类:基于排序的算法(MergeJoin)以及基
    # `, T+ i/ O( i9 t! P5 Y' n+ |于哈希的算法(HashJoin)。对于MergeJoin,首先使用Sort运算符分别对输入表格预. A+ }# r+ s2 n+ I" ?% ~( C1 }" H9 m
    处理,使得两张输入表都在连接列上排好序,接着按顺序迭代两张输入表,合并连
    # n5 `' m# T: ?5 c接列相同的行并输出;对于HashJoin,首先根据连接列计算哈希值K,并分别将两张2 W- q+ x; Z  z- D
    输入表格的数据写入到第K个桶中。接着,对每个哈希桶按照连接列排序。最后,依
    1 [/ p4 K/ l# v次对每个哈希桶合并连接列相同的行并输出。$ S+ `! q# B, D. }7 G1 G
    子查询分为两种:关联子查询和非关联子查询,其中比较常用的是使用IN子句
    # [9 D6 A( |/ F1 g( b# |的非关联子查询。举例如下:) F/ V+ R9 {3 u2 u/ Y* o9 B8 j
    例10-3 假设有两张表格:item(商品表,包括商品号item_id,商品名
    % g" ?- D5 A" K. D' D  ditem_name,分类号category_id,),category(类别表,包括分类号category_id,分
    8 x. H7 i, c# F8 S9 T类名category_name)。如果需要查询分类号出现在category表中商品,可以采用图10-* r. ~& T4 s7 J, X' w/ v3 ~
    4左边的IN子查询,而这个子查询将被自动转化为图10-4右边的等值连接。如果5 x/ q, h6 r5 }2 [, a
    category表中的category_id列有重复,表连接之前还需要使用distinct运算符来删除重
    2 i0 d& ~, X8 [8 X) A/ V, H复的记录。# }+ q' I  c* }
    图 10-4 IN子查询转化为等值连接% d1 Q; D5 o/ j( U! |+ p! q
    例10-4 例10-3中,如果category表只包含category_id为1~10的记录,那么,可
    3 k$ F% G( z1 J* r- P( e7 G以将IN子查询写成图10-5中的常量表达式。2 L3 l6 t+ A# d, u* V# Q- g8 b
    图 10-5 IN子查询转化为常量表达式6 V, b8 r' a" T% ?# K  O
    转化为常量表达式后,MergeServer执行SQL计算时,可以将IN后面的常量列表
    : Q8 v/ Y" f3 @: U- A! J发送给ChunkServer,ChunkServer只返回category_id在常量列表中的商品记录,而不是9 ^: s! Y7 G$ E5 F4 t0 O# `; H+ H
    将所有的记录返回给MergeServer过滤,从而减少二者之间传输的数据量。
    ' F; [% ]9 T" j; \OceanBase多表操作做得还很粗糙,例如不支持嵌套连接(Nested Loop Join),
    4 s% d9 y1 q% P' \  f/ T1 `不支持非等值连接,不支持查询优化等,后续将在合适的时间对这一部分代码进行
    & d& ^4 w9 O4 i( _9 x6 ]重构。* M0 y- u2 K( N/ q
    10.2.4 SQL执行本地化* k! H9 ~7 Y! I
    MergeServer包含SQL执行模块MS-SQL,ChunkServer也包含SQL执行模块CS-
    : G. C. u; }0 O* Q3 z+ mSQL,那么,如何区分二者的功能呢?多表操作由MergeServer执行,对于单表操
    ) ]2 O  \# B# c0 r1 _5 w: N0 y3 u作,OceanBase设计的基本原则是尽量支持SQL计算本地化,保持数据节点与计算节( O, }" T' m# @' |! S
    点一致,也就是说,只要ChunkServer能够实现的操作,原则上都应该由它来完成。5 {: Y$ h' s1 n& E* B2 `
    ●TableScan:每个ChunkServer扫描各自子表范围内的数据,由MergeServer合并
    : e2 n; y9 r3 X& xChunkServer返回的部分结果。
    ) G8 p1 H0 P8 u" q2 E, c) i●Filter:对基本表的过滤集成在TableScan操作符中,由ChunkServer完成。对分( m( p6 r- h0 `7 Z6 M
    组后的结果执行过滤(Having)集成在GroupBy操作符中,一般情况下由MergeServer8 S9 a3 H/ L* H9 `
    完成;但是,如果能够确定每个分组的所有数据行只属于同一个子表,比如SQL请求1 P, m0 ]2 [- m4 q
    只涉及一个tablet,那么,分组以及分组后的过滤操作符可以由ChunkServer完成。
    5 o6 Q: q- @0 Z8 D" |( w# s. I8 t●Projection:对基本表的投影集成在TableScan操作符中,由ChunkServer完成,
    + ]. s+ \) ?8 I7 [3 L对最终结果的投影由MergeServer完成。
    5 e5 v9 j' r+ ?% K: x* B●GroupBy:如果SQL读取的数据只在一个子表上,那么由该子表所在的
    8 S9 y& i) o7 @$ `8 f6 f/ T  KChunkServer完成分组操作;否则,每台ChunkServer各自完成部分数据的分组操作,
    ; n& P5 o7 _6 w3 R. c执行聚合运算后得到部分结果,再由MergeServer合并所有ChunkServer返回的部分结
    : E+ D' R, \; y$ ?3 C果,对于属于同一个分组的数据再次执行聚合运算。某些聚合运算需要做特殊处( @7 K- Y3 _; {" n. k0 z
    理,比如avg,需要转化为sum和count操作发送给ChunkServer,MergeServer合并
    ! n# {6 Z& ], DChunkServer返回的部分结果后计算出最终的sum和count值,并通过sum/count得到avg
    0 d  z, H( z$ k/ g; z9 M& ]的最终结果。2 @: I- t! C+ S; g
    ●Sort:如果SQL读取的数据只在一个子表上,那么由该子表所在的ChunkServer8 g# Y7 J) g7 q7 ~
    完成排序操作;否则,每台ChunkServer各自完成部分数据的排序,并将排好序的部
    # c7 O/ Y4 i) v0 s% v' R分数据返回MergeServer,再由MergeServer执行多路归并。2 `5 w: d) s. y) y8 g) Y! ]- h
    ●Limit:Limit操作一般由MergeServer完成,但是,如果请求的数据只在一个子! l2 u1 w0 C1 {+ n
    表上,可以由ChunkServer完成,这往往会大大减少MergeServer与ChunkServer之间传
    ; v/ c) s% ?" V4 Y4 D% e& k输的数据量。' Z3 k+ v1 M  j7 `
    ●Distinct:Distinct与GroupBy类似。ChunkServer先完成部分数据的去重,再由9 B- U7 N9 D/ g: @  r( l1 ]6 N% V8 ~
    MergeServer进行整体去重。
    1 p5 C5 h3 v, b' a' r1 G  d- Y例10-5 图10-2中的SQL语句为"select c1,sum(c2)from t1 where c3=10 group. n" A' y0 Z' _( m6 m6 ^) _! u; K
    by c1 having sum(c2)>=10 order by c1 limit 0,20"。执行步骤如下:7 N! V) u( _+ L, N9 d
    1)ChunkServer调用TableScan操作符,读取子表t1中的数据,该操作符还将执行
    " B3 c5 r3 \3 o% O. P6 v  ~' ?投影(Project)和过滤(Filter),返回的结果只包含c3=10的数据行,且每行只包含
    : h0 s* k/ X8 {6 W; f# nc1、c2、c3三列。- R% D' b5 U/ u; d
    2)ChunkServer调用HashGroupBy操作符(假设采用基于哈希的分组算法),按+ ~- t; J5 b! _5 c4 C& G3 E+ X- n
    照c1对数据分组,同时计算每个分组内c2列的总和sum(c2)。
    0 q1 f$ n2 t0 T3)每个ChunkServer将分组后的部分结果返回MergeServer,MergeServer将来自不
    2 }. f: N# ~' U9 [* C; u( j同ChunkServer的c1列相同的行合并在一起,再次执行sum运算。
    ' `2 R: U- h& S4)MergeServer调用Filter操作符,过滤第3)步生成的最终结果,只返回
    # ]3 j+ z! i' F: ?$ W( usum(c2)>=10的行。, R4 z6 ^3 A+ |
    5)MergeServer调用Sort操作符将结果按照c1排序。/ y6 a  A, q  ]( ]$ D
    6)MergeServer调用Project操作符,只返回c1和sum(c2)这两列数据。) x3 T) v) O  \1 a  ?( t! J$ @$ L) ~! }
    7)MergeServer调用Limit操作符执行分页操作,只返回前20条数据。1 n0 z5 b6 c2 ]8 n& H5 E2 i9 f
    当然,如果能够确定请求的数据全部属于同一个子表,那么,所有的物理运算2 q. y: W- `4 r1 a% {
    符都可以由ChunkServer执行,MergeServer只需要将ChunkServer计算得到的结果转发
    ' C, A) m( O8 e6 P0 O% o+ \给客户端。2 J0 Z* j1 x5 z

    ' P' ]# a0 t0 \' x: @- c$ P
    * w) x% d# k9 L5 N3 G0 }6 K$ f% k
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|Java自学网

    GMT+8, 2024-4-29 12:07 , Processed in 0.126451 second(s), 31 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

    快速回复 返回顶部 返回列表