2 DataLake — 批流一体化的追风者( 四 )


如果 outer join 是执行 MERGE 的瓶颈(比如重写文件花费的时间太长了) , 那么我们可以采用以下的策略解决:
调整的阈值 。如果我们使用 full outer join, Spark 则无法进行join, 但是如果我们使用 right outer join, Spark 则可以使用;我们可以根据实际情况来调整的阈值;缓存table / .
5.5 处理多个并发的读取和写入
现在我们已经在高层次上了解了事务日志如何工作的 , 现在我们来谈谈并发性先关的内容 。到目前为止 , 我们的示例主要涵盖了用户线性提交事务或至少没有冲突的情况 。但是当Delta Lake处理多个并发读写时会发生什么?答案很简单 , 由于Delta Lake由Spark 提供支持 , 因此提供了可以让多个用户同时修改表的功能 , 为了处理这些并发情况 , Delta Lake 采用了乐观的并发控制
什么是乐观并发控制?
 , 它是假设数据一般情况不会造成冲突 , 所以在数据进行提交更新的时候 , 才会正式对数据的冲突与否进行检测 , 如果冲突 , 则返回给用户异常信息 , 让用户决定如何去做 。乐观锁适用于读多写少的场景 , 这样可以提高程序的吞吐量 。乐观并发控制是一种处理并发事务的方法 , 它假定不同用户对表所做的事务(更改)可以在不相互冲突的情况下完成 。它的速度快得令人难以置信 , 因为当处理 PB 级的数据时 , 用户很可能同时处理数据的不同部分 , 从而允许他们同时完成不冲突的事务 。
例如 , 假设你和我正在一起玩拼图游戏 。只要我们都在做拼图的不同部分——比如你在角落里 , 我在边缘上——我们没有理由不能同时做更大拼图的那一部分 , 并且以两倍的速度完成拼图 。只有当我们同时需要相同的部件时 , 才会产生冲突 。这就是乐观并发控制 。
相反 , 一些数据库系统使用悲观锁定的概念 , 这是假设最坏的情况——即使我们有10,000块拼图 , 在某个时候我们肯定需要相同的拼图——这导致了太多的冲突 。为了解决这个问题 , 它的理由是 , 应该只允许一个人同时做拼图 , 并把其他人都锁在房间外面 。这不是一个快速(或友好)解决难题的方法!当然 , 即使使用乐观并发控制 , 有时用户也会尝试同时修改数据的相同部分 。幸运的是 , Delta Lake 有相应的协议处理它 。
乐观地解决冲突
为了提供ACID事务 , Delta Lake 有一个协议 , 用于确定提交应该如何排序(在数据库中称为 ) , 并确定在同时执行两个或多个提交时应该做什么 。Delta Lake通过实现互斥( )规则来处理这些情况 , 然后尝试乐观地解决任何冲突 。该协议允许Delta Lake遵循ACID隔离原则 , 该原则确保多个并发写操作之后的表的结果状态与那些连续发生的写操作相同 , 并且是彼此隔离的 。一般来说 , 这个过程是这样进行的:
5.6约束如何工作?
Delta Lake对写入进行校验 , 也就是说所有表格的写入操作都会用表的做兼容性检查 。如果不兼容 , Delta Lake将会撤销这次事务(没有任何数据写入) , 并且返回相应的异常信息告知用户 。Delta Lake 通过以下准则判断一次写入是否兼容 , 即对写入的必须满足:
5.7 Delta Lake 上的原子性实现
原子性是ACID事务的四个属性之一 , 它可以保证在Delta Lake上执行的操作(如或)要么全部成功要么全部不成功 。如果没有此属性 , 硬件故障或软件错误很容易导致数据仅部分写入表中 , 从而导致数据混乱或损坏 。