我们在导入时添加了条件的功能,只有条件被满足时才会进行这个更新。目前仅支持固定的条件。当导入的数据是乱序或者由于并发导入导致数据乱序,为了防止乱序导的数据把新的数据给覆盖掉,数据中一般会有一个时间戳字段代表该行的修改时间。这样在更新时可以指定一个条件,当这个时间戳大于当前时间时才进行这个更新操作,否则就忽略该更新行。假设导入的时记录是 src,要覆盖的目的是 dest。上面提到条件可以用 src.ts > dest.ts 来表示。当前仅实现了这一种条件表达式,但后面我们会添加更加通用的表达式支持,让它变成更加通用的条件更新。
4、高频导入优化
针对高频导入导致的各种问题,比如 too many versions、too many pending versions 的报错导致整个导入失败。我们对 publish、compaction 做了大量的优化,比如对 publish 的 task 并行执行和 rocks DB 元数据提交的并行执行,可以大大缩短 publish 的延迟,从而提升整个事务的吞吐能力。另外针对 compaction,我们添加了劣势的 vertical group 的 compaction 来提升 compaction 的性能。我们还设计了新的 compaction 机制来解决 BE 中当 tablet 数量特别大时 compaction 的调度问题。
针对 Flink CDC 同步任务并发导致的事务数量成倍增加的问题,我们新增加了基于 streamload 的事务导入接口。原来每个 Flink Sink 的 task 会单独对应一个导入事务,导致事务数量成倍增加。使用新的事务接口之后,可以将多个导入任务合并成一个事务。在定期 Sink 开始前,开启这个事务,然后并行导入写入数据,最后全部 task 完成数据的传输后,整体再提交这个事务。在上面这个例子中,总事务数就可以从 4 个减少到 1 个。高频导入的问题,本质上是事务数量多的问题,通过降低事务数量,可以避免高频导入带来的一系列问题。
5、DML
原来的 duplicate key、aggregate key、uniq key 表模型对 delete 是有支持的,但是它只支持简单的表达式,具体是通过在一个版本中记录 delete 相关的元数据,然后在运行时重新进行过滤的方式来实现的,这样对查询性能有很大的影响,特别是多次使用 delete 时。主键模型新添加了对 update 和 delete 语句的支持,并且提供了更加完整的功能。语句中可以包含更加复杂的表达式和子查询等。当然它距离目前商业数据库 update delete 的功能还有一些距离,我们还在持续地完善中。
在事务层面,DML 本质上和纯写入事务的导入和纯读取事务的查询都不太相同。DML 是一个读写事务,在事务处理层面上,比导入和查询要复杂一些。目前 StarRocks 中导入和查询的事务隔离级别是最高的。主键模型引入 update 和 delete 语句之后,目前这两个语句隔离级别只能达到 read committed 的级别。在 AP 的大部分场景中可以基本满足需求。对事务隔离级别有强需求的一些应用,我们后期也计划提供支持,具体可能通过添加表锁的方式,但这种方式对事务的并发能力有一些影响。
随着 update 和 delete 功能的完善和存储引擎功能的增多,未来还会考虑添加 merge into 语法的支持。我们认为 DML 功能的完善是实时数据分析从 ETL 模式向 ERT 模式演化的一个重要的前提。在 ERT 模式下,原始数据可以直接导入数仓或者目前更加流行的互仓,通过 DML 和物化视图在数仓内构建处理数据流,可以极大地简化数据流的构建难度和成本。