java自学网VIP

Java自学网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2387|回复: 0

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

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

    [LV.Master]出神入化

    2025

    主题

    3683

    帖子

    6万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    66345

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

    发表于 2017-3-10 13:47:36 | 显示全部楼层 |阅读模式
    10.2 只读事务" x+ ~; p# `/ E
    只读事务(SELECT语句),经过词法分析、语法分析,预处理后,转化为逻辑
    & V; F% n/ X* R: D7 Q2 L查询计划和物理查询计划。以SQL语句select c1,c2 from t1 where id=1 group by c1& ?# }! v. J6 C) Z! [# h& S
    order by c2为例,MergeServer收到该语句后将调用ObSql类的静态方法1 D! C3 @, i3 t7 j; l  e* l
    direct_execute,执行步骤如下:0 g" f: D! T- r9 K
    1)调用flex、bison解析SQL语句生成一个语法树。
    ; W. W+ s1 B$ F5 N! i) p& q2)解析语法树,生成逻辑执行计划ObSelectStmt。ObSelectStmt结构中记录了, X: x& y. j+ d: b/ F8 v
    SQL语句扫描的表格名(t1),投影列(c1,c2),过滤条件(id=1),分组列
    : v: G; t- a( O; `5 o, X1 b(c1)以及排序列(c2)。# @9 A# R! y( K' O! S" e
    3)根据逻辑执行计划生成物理执行计划。ObSelectStmt只是表达了一种意图,
    1 N% W+ V: {+ `. g  e* R) {但并不知道实际如何执行,ObTransformer类的generate_physical_plan将ObSelectStmt转
    ( d+ B) @3 @' d6 a( i6 a7 h化为物理执行计划。
    7 W- c" r/ X' ~逻辑查询计划的改进以及物理查询计划的选择,即查询优化器,是关系数据库
    : `4 P# x! y- L/ _1 X最难的部分,OceanBase目前在这一部分的工作不多。因此,本节不会涉及太多关于6 k  _; o/ w$ I) s: ^& f
    如何生成物理查询计划的内容,下面仅以两个例子说明OceanBase的物理查询计划。
    9 ]0 i4 \/ @3 g; T例10-1 假设有一个单表SQL语句如图10-2所示。
    2 Z+ O8 X' @0 a5 R, i! S/ @' C, x图 10-2 单表物理查询计划示例! h' Q8 O, F- ~& x3 w8 g
    单表SQL语句执行过程如下:  i5 g5 H  a4 T, W( \1 B+ Y
    1)调用TableScan操作符,读取子表t1中的数据,该操作符还将执行投影
    - ]% d8 q! b2 Q: T" K(Project)和过滤(Filter),返回的结果只包含c3=10的数据行,且每行只包含c1、
    : x8 J# m5 s  C- f/ ^4 @$ Jc2、c3三列。( y% o- B' H  V$ i8 v0 I- s9 t
    2)调用HashGroupBy操作符(假设采用基于哈希的分组算法),按照c1对数据
    1 U4 c# N# P- X* T9 {# e0 Z* C分组,同时计算每个分组内c2列的总和。
    ! G3 i! t) h1 A3)调用Filter操作符,过滤分组后生成的结果,只返回上一层sum(c2)>=10的
    4 \1 @* z9 E3 R- J4 [行。, h5 `" q2 L* F* l' d/ q% C
    4)调用Sort操作符将结果按照c1排序。
    % p8 N- ^3 b; u5)调用Project操作符,只返回c1和sum(c2)这两列数据。5 [+ V7 f, Z" L/ {
    6)调用Limit操作符执行分页操作,只返回前20条数据。
    : ]( S& a- }; a- t8 d( e例10-2 假设有一个需要联表的SQL语句如图10-3所示。1 U( f, C) p. ^" U* B  W" M5 Q
    图 10-3 多表物理查询计划示例' A0 _% i7 O5 h& N% n, U$ D) M
    多表SQL语句执行过程如下:
    ) h2 i5 G, M9 v6 s( Y! a1)调用TableScan分别读取t1和t2的数据。对于t1,使用条件c3=10对结果进行过
    2 V' F/ J: s" A1 S3 |$ N滤,t1和t2都只需要返回c1,c2,c3这三列数据。
    * F. Y, [( r0 o: d/ t+ M2)假设采用基于排序的表连接算法,t1和t2分别按照t1.c2和t2.c2排序后,调用" R# H0 [3 |2 n* O" ?8 f
    Merge Join运算符,以t1.c2=t2.c2为条件执行等值连接。& k: R" l5 J; D$ W# j
    3)调用HashGroupBy运算符(假设采用基于哈希的分组算法),按照t1.c1对数1 t( g+ ]1 Z# t2 S+ p1 x! B; P
    据分组,同时计算每个分组内t2.c3列的总和。* y9 a8 n# s) e- t0 E+ A
    4)调用Filter运算符,过滤分组后的生成的结果,只返回上一层sum(t2.c3)>
      v1 R+ W/ U# q1 N5 a5 i8 u=10的行。+ y3 j3 r/ ?! e, a4 L/ r" U
    5)调用Sort操作符将结果按照t1.c1排序。
    % s8 {0 ?$ U% m; s6 w$ q: V6)调用Project操作符,只返回t1.c1和sum(t2.c3)这两列数据。" _' @5 \2 @% Y! |6 f% W) R
    7)调用Limit操作符执行分页操作,只返回前20条数据。' p8 C( h& y7 |! |* W: P: O
    10.2.1 物理操作符接口
    6 d( X# Q$ U" u! f' @2 G  V9.4.2节介绍一期分布式存储引擎中的迭代器接口为ObIterator,通过它,可以将8 d0 ?7 t+ m$ }, A# j
    读到的数据以cell为单位逐个迭代出来。然而,数据库操作总是以行为单位的,因' j* E8 Q- R: U# z* q3 {
    此,二期实现数据库功能层时考虑将基于cell的迭代器修改为基于行的迭代器。, o. s9 b0 l! W+ @
    行迭代器接口如下:
    ' |" f# o. q8 m//ObRow表示一行数据内容
    & h' d2 R. k6 N: ?( s9 wclass ObRow
    0 [2 _1 j; O* h7 T1 x$ @{
    * G/ n# w( O, T) `/ k6 i3 G  v+ Z& `+ _public:
    ; h1 F' x% A# Q4 M//根据表ID以及列ID获得指定cell" H) Z& [/ C  X9 j% f
    //@param[in]table_id表格ID+ K1 [3 r5 f* x& V: F+ j
    //@param[in]column_id列ID% D5 f, u/ W& L7 @3 a: K4 W9 Q
    //@param[out]cell读到的cell
    6 J  ]% h! }9 @' t( Nint get_cell(const uint64_t table_id,const uint64_t column_id,ObObj*&cell);
      I' ]" J& H$ S- G4 }//获取第cell_idx个cell
      G: u, g5 L9 Uint raw_get_cell(const int64_t cell_idx,const ObObj*&cell,uint64_t&table_id,
    1 @$ ~' Y* G+ n3 S6 m, ruint64_t&column_id);( c, I/ ?& z+ q4 s* c( W
    //获取本行的列数
    ) w* S0 k. _3 Q% ?$ |% Y8 M% ^int64_t get_column_num()const;; K& t. p8 v9 n7 Y
    };
    1 [8 q. M/ {" i; X" w/ n2 O, n( b每一行数据(ObRow)包括多个列,每个列的内容包括所在的表9 J* `/ @" Z! Q# s
    ID(table_id),列ID(column_id)以及列内容(cell)。ObRow提供两种访问方  w# b! O0 p, T' k$ c9 ]3 }
    式:根据table_id和column_id随机访问某个列,以及根据列下标(cell_idx)获取某个
    - ^7 d" ]- R! T4 y0 v指定列。$ b8 ^. q# ^- ]2 x- [
    物理运算符接口如下:
    4 J" T4 o& g# L//物理运算符接口  |% O/ h+ H' ]4 }' b. F
    class ObPhyOperator
    ( g1 F1 [! `, i, O7 N2 C8 P8 B{
    6 F9 I  i( t2 d. C4 x3 n* S) t# Upublic:
    ) g& ^! |  q; G% \; P. j( a//添加子运算符,所有非叶子节点物理运算符都需要调用该接口7 E- f* `- w6 A
    virtual int set_child(int32_t child_idx,ObPhyOperator&child_operator);
    ' A, H" m2 V! C: p4 L1 U( _5 ?//打开物理运算符。申请资源,打开子运算符等
    ' m; U1 }( `( M9 C" Ovirtual int open()=0;
    5 q% }% u( J! j# Z//关闭物理运算符。释放资源,关闭子运算符等# b3 s  E1 @* F# U* A
    virtual int close()=0;* j' o8 m* {+ t3 r! O0 O/ t
    //获得下一行数据内容8 B2 k6 u9 S5 p
    //@param[out]row下一行数据内容的引用
    3 _4 U9 ]' T& _3 E8 l//@return返回码,包括成功、迭代过程中出现错误以及迭代完成
    / e# _5 A. ^8 l, z# Uvirtual int get_next_row(const ObRow*&row)=0;$ y6 s: j5 Z% K. ]( j/ X5 a: G
    };: M3 y& G9 Z+ q# m* G! _* ?
    ObPhyOperator每次获取一行数据,使用方法如下:( P9 d8 N/ x! H4 y& ]
    ObPhyOperator root_operator=root_operator_;//根运算符
    5 |& d" Z2 C+ K0 wroot_operator->open();
    9 v0 R5 Z# u) m3 b! D: vObRow*row=NULL;
    , I) w( S6 Q; M1 l7 o6 Twhile(OB_SUCCESS==root_operator->get_next_row(row))
    " {/ @1 u# `$ ?0 ?) }' h0 G, T! a{
    9 V7 R' R; U5 I, l, P4 QOutput(row);//输出本行* B" z! a0 a# E
    }7 g/ x2 F0 s7 |! _5 ?
    root_operator->close();3 k1 ~# r: w2 A) g. _
    为什么ObPhyOperator类中有一个set_child接口呢?这是因为所有的物理运算符构
    , u2 x- D5 Q4 B9 _# \. J# O成一个树,每个物理运算的输出结果都可以认为是一个临时的二维表,树中孩子节( ^8 b% ?1 Y# B
    点的输出总是作为它的父亲节点的输入。例10-1中,叶子节点为一个TableScan类型0 ~. D" e: G- L( r4 n
    的物理运算符(称为table_scan_op),它的父亲节点为一个HashGroupBy类型的物理4 a4 {; h& c( k+ N* g: T
    运算符(称为hash_group_by_op),接下来依次为Filter类型物理运算符filter_op,Sort
    8 X+ _: c1 z: z5 K9 L' O类型物理运算符sort_op,Project类型物理运算符project_op,Limit类型物理运算符' i) _8 i, B* r
    limit_op。其中,limit_op为根运算符。那么,生成物理运算符时将执行如下语句:6 ~6 i! x% v. Z; U* @( ?
    limit_op->set_child(0,project_op);/ m/ ^+ w2 }" [
    project_op->set_child(0,sort_op);
    " m# K+ h+ f# f& x, Z' Q6 lsort_op->set_child(0,filter_op);! K4 R) l% U& r8 d% _; O
    filter_op->set_child(0,hash_group_by_op);
    7 I) [$ ]$ G$ Z. Zhash_group_by_op->set_child(0,table_scan_op);0 H" y% i8 b5 I4 f% I7 O
    root_op=limit_op;
    1 D  J6 \5 u/ z! wSQL最终执行时,只需要迭代root_op(即limit_op)就能够把需要的数据依次迭* V! g# Z8 n5 t2 j2 _8 Q/ G7 N% Z
    代出来。limit_op发现前一批数据迭代完成则驱动下层的project_op获取下一批数据,# W4 J% h& m: j8 n' W6 d
    project_op发现前一批数据迭代完成则驱动下层的sort_op获取下一批数据。以此类
    * V2 b+ g3 d( _5 z; z. X5 q推,直到最底层的table_scan_op不断地从原始表t1中读取数据。6 k/ n3 `6 I; \3 H& j2 S
    10.2.2 单表操作
    % `: \3 x& a+ @单表相关的物理运算符包括:: h! l/ X  D2 q/ S7 C3 j* a% W
    ●TableScan:扫描某个表格,MergeServer将扫描请求发给请求的各个子表所在
    ) R% ]0 X: W% e7 Q6 @的ChunkServer,并将ChunkServer返回的结果按照子表范围拼接起来作为输出。如果3 |3 [. l- x0 c# W  ?
    请求涉及多个子表,TabletScan可由多台ChunkServer并发执行。/ Y2 X  V- {' w9 Q" M$ H
    ●Filter:针对每行数据,判断是否满足过滤条件。
    ; L3 t7 I" w8 X# t●Projection:对输入的每一行,根据定义的输出表达式,计算输出结果行。: Y) N$ _. q/ H- s( e2 J& x3 L! G) j
    ●GroupBy:把输入数据按照指定列进行聚集,对聚集后的每组数据可以执行计; \: Q# Q; e$ o, {9 j
    数(count)、求和(sum)、计算最小值(min)、计算最大值(max)、计算平均值7 K. u6 X$ `  R6 V: z  k
    (avg)等聚集操作。
    3 m1 E+ B/ _, Z, u/ r●Sort:对输入数据进行整体排序,如果内存不够,需要使用外排序。* m4 d2 N# X" ]; S- R& ^
    ●Limit(offset,count):返回行号在[offset,offset+count)范围内的行。
    8 o, Z/ i/ _  Q* \7 Z+ F●Distinct:消除某些列相同的重复行。
    4 Q) \$ ?) `# D  z+ z( AGroupBy、Distinct物理操作符可以通过基于排序的算法实现,也可以通过基于哈
    8 L& ]  w2 J. u1 H希的算法实现,分别对应HashGroupBy和MergeGroupBy,以及HashDistinct和
    # F( {4 n2 x, \MergeDistinct。下面分别讨论排序算法和哈希算法。1 h  [$ N, O' Y3 \) I& R2 y% Z
    1.排序算法' l0 G1 H  O+ A( l% }5 ]$ U+ ]
    MergeGroupBy、MergeDistinct以及Sort都需要使用排序算法。通用的<key,value  J# N6 M  \1 f1 E+ ?+ Z  u
    >排序器可以分为两个阶段:  o) [: l3 l2 r  s- d
    ●数据收集:在数据收集阶段,调用者将<key,value>对依次加入到排序器。如
    9 G# V$ v' e4 O/ p果数据总量超过排序器的内存上限,需要首先将内存中的数据排好序,并存储到外
    & K# D: ~' e5 j% p7 R, V/ G部磁盘中。
    3 Z+ X, y8 S* Q  [8 s+ o2 w●迭代输出:迭代第一行数据时,内存中可能有一部分未排序的数据,磁盘中也
    / x& }9 J8 g4 |可能有几路已经排好序的数据。因此,首先将内存中的数据排好序。如果数据总量/ j" b5 s# p9 h* f! R' \
    不超过排序器内存上限,那么将内存中已经排好序的数据按行迭代输出(内排
      d# Z6 m6 X! B$ s+ B/ }5 M, L序);否则,对内存和磁盘中的部分有序数据执行多路归并,一边归并一边将结果
    ) Y8 A% p7 D9 n0 Z: }- S$ `迭代输出。3 A; ^) j7 n4 q
    2.哈希算法3 M  [; P7 h: @! y- h
    HashGroupBy以及HashDistinct都需要使用哈希算法。假设需要对<key,value>对' a* _' M5 |$ ]6 w. q& d, y% Y! [
    按照key分组,那么首先使用key计算哈希值K,并将这个<key,value>对写入到第K个# @# N8 r- u; W+ Q$ u5 Y/ ~" Q
    桶中。不同的key可能对应相同的哈希桶,因此,还需要对每个哈希桶内的<
    9 Y/ U( i1 ^0 ~8 }. Pkey,value>对排序,这样才能使得key相同的元组能够连续迭代出来。哈希算法的难4 w6 w4 P$ l3 I) k2 R
    点在于数据总量超过内存上限的处理,由于篇幅有限,请自行思考。) d& q+ D# P7 h" v; ?5 B  A
    10.2.3 多表操作
    ! t7 J3 t6 _) `* S5 v0 E7 z8 n多表相关的物理操作符主要是Join。最为常见的Join类型包括两种:内连接% P' F/ g) J4 {7 f* o) h2 k( i
    (Inner Join)和左外连接(Left Outer Join),而且基本都是等值连接。如果需要连接
    7 O2 x# O% K- y* V' Q多张表,可以先连接前两张表,再将前两张表连接生成的结果(相当于一张临时# J, h" {: H2 i
    表)与第三张表格连接,以此类推。& I  |7 p# N. Y' c4 N8 \) s1 G
    两张表实现等值连接方式主要分为两类:基于排序的算法(MergeJoin)以及基2 G5 x% Q7 c) F; Y! ^
    于哈希的算法(HashJoin)。对于MergeJoin,首先使用Sort运算符分别对输入表格预) u/ q7 R' P' @4 s, e  j
    处理,使得两张输入表都在连接列上排好序,接着按顺序迭代两张输入表,合并连! W1 o' |: n. |6 K" M0 ^
    接列相同的行并输出;对于HashJoin,首先根据连接列计算哈希值K,并分别将两张
    ) H: ^0 l/ r0 I输入表格的数据写入到第K个桶中。接着,对每个哈希桶按照连接列排序。最后,依5 Z; z6 U1 q8 Q" ?9 c- |* S  [
    次对每个哈希桶合并连接列相同的行并输出。# i; g: b! z, s( M# {7 s
    子查询分为两种:关联子查询和非关联子查询,其中比较常用的是使用IN子句0 M' j/ n- O+ O: ^0 y3 u9 W
    的非关联子查询。举例如下:0 B: c; V2 s( R
    例10-3 假设有两张表格:item(商品表,包括商品号item_id,商品名
    * W& y" B7 `; o4 Y5 ], [1 Z0 C( d) k2 citem_name,分类号category_id,),category(类别表,包括分类号category_id,分
    ) B  a. p8 a7 X, F类名category_name)。如果需要查询分类号出现在category表中商品,可以采用图10-
    0 r% E8 P! u+ k6 y! C% @4左边的IN子查询,而这个子查询将被自动转化为图10-4右边的等值连接。如果  v2 a* ~7 z$ v9 A9 T/ S1 {# |
    category表中的category_id列有重复,表连接之前还需要使用distinct运算符来删除重
    - Y5 I+ f& Z* |0 u: I  Y复的记录。1 q4 u% y/ a7 z( X9 Y
    图 10-4 IN子查询转化为等值连接
    8 [& B7 U; M2 j例10-4 例10-3中,如果category表只包含category_id为1~10的记录,那么,可
    ; h& r3 M& G9 s* p8 B4 X以将IN子查询写成图10-5中的常量表达式。
      y4 g4 |" I+ L& K/ x. U图 10-5 IN子查询转化为常量表达式4 C: F, ]2 C1 o$ k1 U
    转化为常量表达式后,MergeServer执行SQL计算时,可以将IN后面的常量列表  _$ J) V( \& R' K/ O, O4 k
    发送给ChunkServer,ChunkServer只返回category_id在常量列表中的商品记录,而不是; i( {& u* f4 z# |. {+ Q; o0 j3 b
    将所有的记录返回给MergeServer过滤,从而减少二者之间传输的数据量。/ w/ L( Q- f+ D4 A* l# X
    OceanBase多表操作做得还很粗糙,例如不支持嵌套连接(Nested Loop Join),
    6 P, }3 ?+ u; O1 F' C6 I不支持非等值连接,不支持查询优化等,后续将在合适的时间对这一部分代码进行0 }& ^- _# a0 _6 P4 @
    重构。
      x6 f3 S  @$ {$ u5 _6 n" A10.2.4 SQL执行本地化3 p9 m; O8 j; H8 G) l
    MergeServer包含SQL执行模块MS-SQL,ChunkServer也包含SQL执行模块CS-. Y$ x5 x& E% {0 r3 R6 t) F" U% f# c
    SQL,那么,如何区分二者的功能呢?多表操作由MergeServer执行,对于单表操, a# ?5 O. u: i7 _3 D* @
    作,OceanBase设计的基本原则是尽量支持SQL计算本地化,保持数据节点与计算节7 U+ f& o- J! }' v" W
    点一致,也就是说,只要ChunkServer能够实现的操作,原则上都应该由它来完成。$ D- O# T* o& r; {2 F, S, v9 }
    ●TableScan:每个ChunkServer扫描各自子表范围内的数据,由MergeServer合并
      y  {; E: l! k  NChunkServer返回的部分结果。& q9 ?$ ]' T% R
    ●Filter:对基本表的过滤集成在TableScan操作符中,由ChunkServer完成。对分) y1 S8 `# F. X0 k8 T' s( F: y
    组后的结果执行过滤(Having)集成在GroupBy操作符中,一般情况下由MergeServer
    ( C# b& T; k/ p% K; Z! X. z9 n完成;但是,如果能够确定每个分组的所有数据行只属于同一个子表,比如SQL请求
    , L' F( x2 T3 }9 f" X# o& n5 z只涉及一个tablet,那么,分组以及分组后的过滤操作符可以由ChunkServer完成。
    ! G/ }  ?( U2 j, ~) a/ F! S+ a●Projection:对基本表的投影集成在TableScan操作符中,由ChunkServer完成,5 t0 j3 V/ A" s5 J) I0 f' V
    对最终结果的投影由MergeServer完成。
    3 V( x: }; I+ Y- G/ {0 Q2 D/ f●GroupBy:如果SQL读取的数据只在一个子表上,那么由该子表所在的
    $ `8 M( t  f! e% B! R9 @' YChunkServer完成分组操作;否则,每台ChunkServer各自完成部分数据的分组操作," g$ h9 C( Q( j* H' i+ |6 a
    执行聚合运算后得到部分结果,再由MergeServer合并所有ChunkServer返回的部分结
    % [- f, g# A) Q& R9 |果,对于属于同一个分组的数据再次执行聚合运算。某些聚合运算需要做特殊处) k4 z, p' d7 @0 ^2 k6 G1 i7 a6 |( `8 M# D
    理,比如avg,需要转化为sum和count操作发送给ChunkServer,MergeServer合并& C4 b0 e2 ?6 M3 t6 B3 u4 f
    ChunkServer返回的部分结果后计算出最终的sum和count值,并通过sum/count得到avg
    $ A5 g% T2 Z1 r  J的最终结果。$ p& V- c& d" w# {
    ●Sort:如果SQL读取的数据只在一个子表上,那么由该子表所在的ChunkServer! N( G' s* A4 T8 ~; j  C5 U( H8 d
    完成排序操作;否则,每台ChunkServer各自完成部分数据的排序,并将排好序的部8 Y! k$ G) Z3 v
    分数据返回MergeServer,再由MergeServer执行多路归并。
    " Z6 y, K+ l, ?; M4 }2 n●Limit:Limit操作一般由MergeServer完成,但是,如果请求的数据只在一个子
    + O( ^, U* N" R" q; p2 L表上,可以由ChunkServer完成,这往往会大大减少MergeServer与ChunkServer之间传
      Y, d# }, F4 p) u3 _6 G6 V' R输的数据量。
    8 k2 A) M5 y# H4 E●Distinct:Distinct与GroupBy类似。ChunkServer先完成部分数据的去重,再由
    0 p, z# V% o0 X0 I, K# I; S7 {MergeServer进行整体去重。
    9 L" s# d! u( V: n$ z例10-5 图10-2中的SQL语句为"select c1,sum(c2)from t1 where c3=10 group% l* i0 z* r# t' a
    by c1 having sum(c2)>=10 order by c1 limit 0,20"。执行步骤如下:
    2 |; }# h# H/ X3 c, z9 J' q1)ChunkServer调用TableScan操作符,读取子表t1中的数据,该操作符还将执行! X: o9 J2 H; q
    投影(Project)和过滤(Filter),返回的结果只包含c3=10的数据行,且每行只包含
    * q" y$ \$ \+ Z  jc1、c2、c3三列。* Q" P2 ?- f$ P  X4 M, i
    2)ChunkServer调用HashGroupBy操作符(假设采用基于哈希的分组算法),按
    : g6 s8 C, S- `3 I: C- U: k照c1对数据分组,同时计算每个分组内c2列的总和sum(c2)。
    3 t- s8 H4 @5 X. d3)每个ChunkServer将分组后的部分结果返回MergeServer,MergeServer将来自不4 `( Z) y/ b" l) D- G. |3 I
    同ChunkServer的c1列相同的行合并在一起,再次执行sum运算。
    " ?" U4 o' {5 w: j. W  S& ]4)MergeServer调用Filter操作符,过滤第3)步生成的最终结果,只返回
    ( T- x" o! h7 K/ @) o- xsum(c2)>=10的行。: @, ?: I. E: E+ |6 h( E
    5)MergeServer调用Sort操作符将结果按照c1排序。+ `1 t9 K! \6 [8 O
    6)MergeServer调用Project操作符,只返回c1和sum(c2)这两列数据。
    % ~( `/ o+ q8 E4 ~) Z* |9 s" p* l$ N7)MergeServer调用Limit操作符执行分页操作,只返回前20条数据。
    2 b* N9 z; O7 F: ^( w1 Y) W! n3 c, |当然,如果能够确定请求的数据全部属于同一个子表,那么,所有的物理运算
    2 ?# b1 I, H  Z5 o: x符都可以由ChunkServer执行,MergeServer只需要将ChunkServer计算得到的结果转发
    2 m8 {$ K; E0 n; d( ?, E" H$ L给客户端。. {3 z, n7 t3 [! X2 i: D

    2 o1 [0 U' H3 S) O, L; G) [1 @
    9 p1 `" V2 X4 S+ p/ F
    回复

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-11-21 20:38 , Processed in 0.151051 second(s), 32 queries .

    Powered by Javazx

    Copyright © 2012-2022, Javazx Cloud.

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