支援 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 區塊,該區塊由 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 集合的未來,此集合代表關於已處理資料列的連接器特定資訊。通常,這會包含資料列計數,並可能包含諸如建立或變更的檔案或分割區之類的資訊。

ConnectorMetadata DELETE API

實作 DELETE 的連接器必須指定三個 ConnectorMetadata 方法。

  • getDeleteRowIdColumnHandle():

    ColumnHandle getDeleteRowIdColumnHandle(
         ConnectorSession session,
         ConnectorTableHandle tableHandle)
    

    此方法傳回的 ColumnHandle 會提供連接器用來識別要刪除的資料列的 rowId 資料行控制代碼,以及連接器完成 DELETE 作業所需的資料列的其他任何欄位。對於 JDBC 連接器,該 rowId 通常是表格的主索引鍵,且不需要其他欄位。對於其他連接器,識別資料列所需資訊通常由多個實體資料行組成。

  • 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 操作。這些行動可能包括提交交易,假設連接器支援交易範例。