支持 DELETEUPDATE

Presto 引擎提供 API 来支持行级 SQL DELETEUPDATE。要实现 DELETEUPDATE,连接器必须

  • 在连接器的 ConnectorPageSource 之上层叠一个 UpdatablePageSource

  • 定义 ConnectorMetadata 方法以获取 rowId 列句柄

  • 使用 beginUpdate()beginDelete() 启动操作

  • 使用 finishUpdate()finishDelete() 完成操作

DELETEUPDATE 数据流

DELETEUPDATE 具有类似的流程

  • 对于每个拆分,连接器将创建一个 UpdatablePageSource 实例,层叠在连接器的 ConnectorPageSource 之上,以代表 Presto 引擎读取页面,并将删除或更新写入底层数据存储。

  • 连接器的 UpdatablePageSource.getNextPage() 实现从底层 ConnectorPageSource 获取下一页,可选地重新格式化页面,然后将其返回到 Presto 引擎。

  • Presto 引擎对读取的页面执行过滤和投影,生成一个已过滤、已投影的结果页面。

  • Presto 引擎将该已过滤、已投影的结果页面传递给连接器的 UpdatablePageSource deleteRows()updateRows() 方法。这些方法将删除或更新持久化到底层数据存储中。

  • 当特定拆分的全部页面都已处理完毕后,Presto 引擎会调用 UpdatablePageSource.finish(),它将返回一个 Collection<Slice>,其中包含表示连接器特定信息的一组片段,这些信息与对 deleteRowsupdateRows 的调用所处理的行有关。

  • 当所有拆分的全部页面都已处理完毕后,Presto 引擎会调用 ConnectorMetadata.finishDelete()finishUpdate,并传递一个包含所有拆分的所有片段的集合。连接器将执行完成操作所需的操作,例如提交事务。

rowId 列句柄抽象

Presto 引擎和连接器使用 rowId 列句柄抽象来就待更新或删除行的标识达成一致。rowId 列句柄对 Presto 引擎来说是不透明的。根据连接器的不同,rowId 列句柄抽象可能代表多个物理列。

用于 DELETE 的 rowId 列句柄

Presto 引擎使用连接器特定的 rowId 列句柄来标识待删除的行,该句柄由连接器的 ConnectorMetadata.getDeleteRowIdColumnHandle() 方法返回,该方法的完整签名为

ColumnHandle getDeleteRowIdColumnHandle(
    ConnectorSession session,
    ConnectorTableHandle tableHandle)

用于 UPDATE 的 rowId 列句柄

Presto 引擎使用连接器特定的 rowId 列句柄来标识待更新的行,该句柄由连接器的 ConnectorMetadata.getUpdateRowIdColumnHandle() 方法返回。除了标识行的列外,对于 UPDATE,rowId 列还将包含连接器执行 UPDATE 操作所需的任何列。

UpdatablePageSource API

如上所述,要支持 DELETEUPDATE,连接器必须定义 UpdatablePageSource 的一个子类,层叠在连接器的 ConnectorPageSource 之上。有趣的方法是

  • Page getNextPage()。当 Presto 引擎调用 getNextPage() 时,UpdatablePageSource 会调用其底层的 ConnectorPageSource.getNextPage() 方法来获取页面。某些连接器在将页面返回到 Presto 引擎之前会重新格式化它。

  • void deleteRows(Block rowIds)。Presto 引擎会调用同一 UpdatablePageSource 实例的 deleteRows() 方法,该实例提供了原始页面,并传递一组 rowId,该组 rowId 由 Presto 引擎根据 ConnectorMetadata.getDeleteRowIdColumnHandle() 返回的列句柄创建。

  • void updateRows(Page page, List<Integer> columnValueAndRowIdChannels)。Presto 引擎会调用同一 UpdatablePageSource 实例的 updateRows() 方法,该实例提供了原始页面,并传递一组投影列,每个投影列代表一列已更新的列,最后一列代表 rowId 列。投影列的顺序由 Presto 引擎定义,该顺序反映在 columnValueAndRowIdChannels 参数中。updateRows() 的工作是

    • 从投影页面中提取已更新的列块和 rowId 块。

    • 按照连接器存储所需的任何顺序将它们组合在一起。

    • 将更新结果存储到底层文件存储中。

  • CompletableFuture<Collection<Slice>> finish()。当拆分的全部页面都已处理完毕后,Presto 引擎会调用 finish()。连接器返回一个包含 Slice 集合的 future,该集合表示连接器特定信息,这些信息与已处理的行有关。通常,这将包括行计数,并且可能包括诸如已创建或更改的文件或分区之类的信息。

ConnectorMetadata DELETE API

实现 DELETE 的连接器必须指定三个 ConnectorMetadata 方法。

  • getDeleteRowIdColumnHandle():

    ColumnHandle getDeleteRowIdColumnHandle(
         ConnectorSession session,
         ConnectorTableHandle tableHandle)
    

    此方法返回的 ColumnHandle 提供 rowId 列句柄,连接器使用该句柄来标识待删除的行,以及连接器完成 DELETE 操作所需的任何其他行字段。对于 JDBC 连接器,该 rowId 通常是表的 primary key,不需要其他字段。对于其他连接器,识别行的所需信息通常由多个物理列组成。

  • beginDelete():

    ConnectorTableHandle beginDelete(
         ConnectorSession session,
         ConnectorTableHandle tableHandle)
    

    作为创建DELETE执行计划的最后一步,连接器的beginDelete()方法被调用,并传入sessiontableHandle

    beginDelete()执行连接器中开始处理DELETE所需的任何编排。此编排因连接器而异。

    beginDelete()返回一个ConnectorTableHandle,其中包含连接器在将句柄传回finishDelete()和拆分生成机制时所需的任何附加信息。对于大多数连接器,返回的表句柄包含一个标志,用于识别表句柄为DELETE操作的表句柄。

  • finishDelete():

    void finishDelete(
        ConnectorSession session,
        ConnectorTableHandle tableHandle,
        Collection<Slice> fragments)
    

    DELETE处理过程中,Presto引擎会累积由UpdatablePageSource.finish()返回的Slice集合。在处理完所有拆分后,引擎会调用finishDelete(),并传入表句柄以及该Slice片段的集合。作为响应,连接器会采取适当的措施来完成Delete操作。这些操作可能包括提交事务,假设连接器支持事务范式。

ConnectorMetadata UPDATE API

实现UPDATE的连接器必须指定三个ConnectorMetadata方法。

  • getUpdateRowIdColumnHandle:

    ColumnHandle getUpdateRowIdColumnHandle(
         ConnectorSession session,
         ConnectorTableHandle tableHandle,
         List<ColumnHandle> updatedColumns)
    

    updatedColumns列表包含由UPDATE操作在表列顺序中更新的所有列的列句柄。

    此方法返回的ColumnHandle提供连接器用于识别要更新的行的rowId,以及连接器完成UPDATE操作所需的行的任何其他字段。

  • beginUpdate:

    ConnectorTableHandle beginUpdate(
         ConnectorSession session,
         ConnectorTableHandle tableHandle,
         List<ColumnHandle> updatedColumns)
    

    作为创建UPDATE执行计划的最后一步,连接器的beginUpdate()方法被调用,并传入定义连接器的UPDATE的参数。除了sessiontableHandle之外,参数还包括在表列顺序中的已更新列句柄列表。

    beginUpdate()执行连接器中开始处理UPDATE所需的任何编排。此编排因连接器而异。

    beginUpdate返回一个ConnectorTableHandle,其中包含连接器在将句柄传回finishUpdate()和拆分生成机制时所需的任何附加信息。对于大多数连接器,返回的表句柄包含一个标志,用于识别表句柄为UPDATE操作的表句柄。对于某些支持分区的连接器,表句柄将反映该分区。

  • finishUpdate:

    void finishUpdate(
        ConnectorSession session,
        ConnectorTableHandle tableHandle,
        Collection<Slice> fragments)
    

    UPDATE处理过程中,Presto引擎会累积由UpdatablePageSource.finish()返回的Slice集合。在处理完所有拆分后,引擎会调用finishUpdate(),并传入表句柄以及该Slice片段的集合。作为响应,连接器会采取适当的措施来完成UPDATE操作。这些操作可能包括提交事务,假设连接器支持事务范式。