数据库操作执行

0. 索引-----trie树

我们希望不用到叶子节点就能判断出是否在树中。
radix trie使用了垂直压缩,既如果分支只有一个孩子节点,则只在分歧处保存指针即可,不再进行无意义的延申。

倒排索引:

B+树并发协议,crab算法

crab算法提出了安全节点的概念,在父节点处会获得子结点的锁,如果子结点是安全结点,则可以释放父结点的锁。

crab算法插入删除操作时,首先会对根节点加w写锁,这会导致并行性下降。可以采用乐观假设,大部分操作都不涉及节点的分裂和合并。因此只需对根和中间节点加读锁,叶子节点加写锁即可。如果判断出需要分裂,则重启操作,从根节点加写锁重新尝试。

一. 如何执行查询操作(Operator Execution)

1. 排序算法

1.1 排序算法

(1)数据可以装进内存中,使用快排等算法。其中Top-K Heap Sort,非常适用于查询指定了ORDER BY且包含LIMIT。
(2)整体数据不能装进内存,使用外部归并排序。

  • 排序阶段:需要对KV对进行排序,这里的Key是指排序比较的属性值。Value的选择有两种,Tuple(Early Materialization)和Record_ID(Late Materialization)
    使用 B B B个buffer进行排序,代表一个run,排序完事后写回硬盘。
  • 合并阶段:使用 B − 1 B-1 B1个buffer,每个buffer都取自上阶段的归并结果,1个buffer存储结果,写满后写回硬盘。

K-way归并排序的代价: 2 N ∗ ( 1 + ⌈ log ⁡ B − 1 ⌈ N / B ⌉ ⌉ ) 2N*(1 + \lceil{\log_{B-1}\lceil N/B \rceil}\rceil) 2N(1+logB1N/B⌉).其中 B B B代表可用的buffer数量,N代表数据page的数量,2代表读和写。

N ≤ ( B − 1 ) m × B N \leq(B-1)^{m} \times B N(B1)m×B. 其中 m m m代表合并pass的数量。

1.2 基于索引的排序

(1)如果需要排序的key已经有了clustering index(文件中的记录也是按照search key的顺序排放)的话,就不需要外部归并排序算法了。假设是B+树,直接对叶子节点进行遍历即可得到排序完的结果。

(2)如果是Secondary Indices,虽然各叶子节点中的数据对应不同的物理block,但其实也可以进行优化,就是对叶子节点每个record_id先不去获取其在物理block,先记录下来其page_id,最后一起获取,从而避免多次随机读取的情况。

1.3 聚合函数

(1)排序的方法实现聚合函数。去除重复tuple、聚合函数、集合操作等都需要先进行排序。

(2)在实现聚合函数中,哈希方法通常效率更高。因为像Group by和 DISTINCT的操作,并不需要结果是有序的(排序做了额外工作)

  • 可以放入内存的情况:根据Group by的Key,直接建立哈希表即可,这样相同的Key必会映射到同一位置,通过某个值对信息维护即可。针对没有提供Group by的查询语句,因为会建立一个空的Key值,这样就相当于默认都会映射到同一个位置。

  • 无法放入内存情况:

    • a) 哈希方法中的分区,假设有B个buffer可用,那么可以划分为B-1个分区,1个buffer用来输入数据,当分区满后写回磁盘。
      这里假设: key值的分布是均匀的。(很多元素具有相同值的话循序扫描也许是更好的方式)
    • b) rehash, 将每个分区读入内存,使用哈希表进行统计。遍历完分区后,丢弃临时哈希表,将结果汇总。
      3.1

2. join算法

(1) join操作输出的数据是什么?
Tuple:直接存储Tuple数据,好处是不需要再从硬盘读取数据,坏处是可能有很多后续操作不需要的数据
Record_ID:后续操作需要读硬盘才能获取完整的数据。更适合列式存储
3.2
(2)使用哪种算法更好?
join操作中,索引可用情况下,拥有较少tuple的作为outer关系更合适
始终将较小的表(page/tuple数量小,视具体算法)作为outer relation
假设R和S表的page分别为 M M M N N N,tuple为 m m m n n n

2.1 Nested Loop Join

(1) NAÏVE :双重循环,对R表中的每个tuple都需要遍历一遍S表,总代价为 M + ( m ∗ N ) M + (m*N) M+(mN)
(2) Block: 对R表中的每个Block遍历S表,总代价为 M + ( M ∗ N ) M + (M*N) M+(MN)
是匹配完整个Block的tuple才释放S表的Block。
如果有 B B B个buffer可用, B − 2 B-2 B2给outer,1个buffer给inner,1个用来输出,总代价为 M + ( ⌈ M / ( B − 2 ) ⌉ ∗ N ) M + (\lceil M/(B-2)\rceil *N) M+(⌈M/(B2)⌉N)
(3)Index:对S表建立索引, C C C代表索引的代价,哈希表为 O ( 1 ) O(1) O(1),B+树为 O ( log ⁡ ( n ) ) ) O(\log(n))) O(log(n))),总代价为 M + ( m ∗ C ) M + (m*C) M+(mC)

2.2 Merge-join

(1)Merge-join算法,需要join的关系需要先根据合并属性值进行排序。(如果事先有序,则使用该算法比较好)
在关系S中收集具有相同JoinAttrs值的tuple。在关系R中去掉小于该JoinAttrs值的记录,找到相等的进行合并。
Merge-cost : ( M + N ) \left( M + N \right) (M+N)

总代价为:Sort-cost + ( M + N ) \left( M + N \right) (M+N)

2.3 Hash Join
  • 可以放入内存的情况:使用一个哈希函数 h 1 h_1 h1遍历outer relation映射join attributes建立哈希表,再遍历inner relation看哈希表中是否存在。

  • 无法放入内存情况:
    Bloom Filter概率模型,判断是否在集合内。如果回答为false,则可确定一定不在哈希表内。 为true时,则有可能在哈希表内
    采用bitmap来实现。一般有两个哈希函数,产生两个哈希值。哈希值再取模 K K K后,再插入bit数组中。其中 K K K代表bitmap的长度。
    类似于聚合函数中的分区操作。递归划分:如果某个分区有很多记录,那么可用再额外的哈希函数进行再次划分

    总代价为: 3 ( M + N ) 3\left( M + N \right) 3(M+N)

根据哈希函数可以将JoinAttrs属性值映射为整数,因此就能对各关系进行划分,有相同属性值的被划分到同一个区域,相当于桶排序的思想。
再进行join时,只需要和对方的同一划分进行匹配即可。

3. processing model

如何去执行一个查询

(1)Iterator Model:每个operator都需要实现Next函数,向上一次返回一个tuple。容易实现输出控制,例如LIMIT 10,根节点只需调用10次Next即可。
(2)Materialization Model:向上一次返回整个关系
(3)Vectorized / Batch Model:向上一次返回一批次tuple

query-evaluation plan(query-execution plan)用来评估查询的一系列原语操作

1.Zone map提前计算好一些统计信息作为元数据,例如最大值最小值等,维护起来可能比较麻烦,更适合写少读多的负载

多索引scan是扫描多个索引,最终将结果整合在一起

3.1 Select算法

只有secondary index时,需要使用bitmap index scan,创建一个和relation的block数量相等的bitmap,扫描叶子节点时,设置相应的bit为1,扫描完毕后根据bitmap决定是否要跳过某些block。

materialized evaluation:每个操作的结果都需建立临时relation,并且写回磁盘。
pipelined evaluation:生成一个tuple,直接传递给下一个操作

3.2 并行process model

给定一个任务,如何分配给不同的worker

(1) inter-query 并行处理不同请求

(2)intra-query 将一个请求划分为不同任务并行执行,用来加速long-running queries。例如并行处理不同的operation

exchange operator负责汇总各fragment的结果

3.2.1 Parallel Sort

(1)Range-Partitioning Sort,类似MapReduce,Map负责读取磁盘数据对数据按照范围进行划分后,发给相应目标节点,目标节点排好序后拼接在一起即可。
(2)Parallel External Sort-Merge, 先在局部并行排序,合并排序结果

4 查询优化

选择更有效的查询计划。分为两个方面:

(1)关系代数层:生成相同集合(不用管顺序)的tuple的SQL语句是等价的,选择更高效的等价表达式。
(2)细节策略:如选择什么算法去执行某个operation,使用什么索引。

pipelined edges:中间结果直接发送给下一步操作,不写回硬盘
materialized edges:写回硬盘

(3)binder负责将SQL中引用的命名对象转换为某种内部标识符

将更具有选择性的条件放在最里面,可以过滤更多东西

4.1 cost-base search

使用成本模型用来估计执行的代价。选取不同plan中代价最少的。

statistics模块收集表中tuple的信息

(1)为简化分析,假设值是均匀分布,并且假定条件是独立的。

需要计算选择率,类似于概率计算的方式。

如果需要对列中出现的不同值维护其准确的出现次数,那么会占用很多内存。实际上,会将列中不同的值划分为不同的bucket。

4.2 join顺序优化

left-deep tree可以最小化写入磁盘的数量。既中间结果不需要写回到磁盘中。

动态规划: 枚举join算法,选择代价最低的,然后枚举表的扫描算法,选择代价最低的。

遗传算法: 对13个表及以上的join才使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值