JDBC 下推
IBM Presto 可以將連結查詢或部分連結查詢的處理下推到連接的 JDBC 資料來源。
加入操作
Presto 將連結查詢轉換為特定的內部表示(連結作業),稱為。'PlanNode' 透過有效地使用連線操作和查詢最佳化技術,Presto 可以有效率地執行複雜的連線查詢。
加入下推
Presto 允許 Connector 將「Join 操作 ( )」委託給底層 資料來源。PlanNode JDBC 連接器應能夠在資料來源層級處理連線謂词(join predicate)。 這個稱為「連結下推」的過程可大幅改善查詢效能。
查詢最佳化
Presto 分析 Join 查詢,以建立最佳的「Join 操作 ( )」。PlanNode 此最佳化過程包括推斷和重組查詢,以改善效能。
以下是一些 Presto 推斷的範例,這些推斷在連線查詢中會造成結構上的差異:
Presto 推理 | 使用者提供的查詢 | 查詢推斷結果 |
---|---|---|
推論移除連接條件 | select * from postgresql.pg.mypg_table1 t1 join postgresql.pg.mypg_table2 t2 on t1.pgfirsttablecolumn=t2.pgsecondtablecolumn where t1.pgfirsttablecolumn=100 |
select * from postgresql.pg.mypg_table1 t1,postgresql.pg.mypg_table2 t2 where t1.pgfirsttablecolumn=100 and t2.pgfirsttablecolumn=100 |
推論從右連接、左連結或交叉連接建立內連結 | SELECT e.first_name_varchar, p.project_name_varchar, p.risk_level_tinyint FROM mysql.tm_lakehouse_engine_db_1.employee e CROSS JOIN mysql.tm_lakehouse_engine_db_1.projects p WHERE e.age_tinyint > p.risk_level_tinyint; |
SELECT e.first_name_varchar, p.project_name_varchar, p.risk_level_tinyint FROM mysql.tm_lakehouse_engine_db_1.employee e, mysql.tm_lakehouse_engine_db_1.projects p WHERE e.age_tinyint > p.risk_level_tinyint; |
左連結和右連結可能會在內部轉換為內部連結,並可能會向下推向特定的連線器。 此外,由於某些條件,內部連接可能無法向下推至特定連接器。
在 Presto JDBC 資料來源中進行 Join 查詢下推的主要注意事項
Presto 驗證 'join operation( )「規格,以執行」join pushdown'。PlanNode 這些規格因資料來源和連線器而異。 不過,以下是 join
在 JDBC 連接器中向下推送時需要滿足的一些一般條件。
- 連接器支援:JDBC 連接器必須能夠處理連線作業。 涉及 Presto 函數或運算符號的複雜操作可能會阻止推倒。
- 連接類型和條件:連線通常應該是內連線,在資料表之間至少有一個共通欄位。 連接條件應涉及相容的資料類型和運算符號。
- 資料庫相容性:底層資料庫必須支援所涉及的特定連接作業和資料類型。 如需詳細資訊,請參閱支援連線下推功能的資料類型和操作員。
- 表群組:來自相同連接器且符合所需標準的資料表可進行群組,以進行下推。
- 設定:Join pushdown 使用會話層級屬性的組合來控制。
若要啟用加入下推,請設定下列會話旗標:
允許向下推至符合條件的資料來源,但僅適用於等值連接(具有等值條件的連接)
SET SESSION optimizer_inner_join_pushdown_enabled = true;
針對符合條件的資料來源,啟用非不等式連線 (具有不等式或基於範圍條件的連線) 的 pushdown 功能。 需要與上述標誌一起設定為 true。
SET SESSION optimizer_inequality_join_pushdown_enabled = true;
在目錄層級啟用部分謂語下推。 這可以將適用的篩選條件與連接子句一起推送到資料來源。
SET SESSION <catalogName>.partial_predicate_push_down = true;
例如,
SET SESSION postgresql.partial_predicate_push_down = true;
雖然這不是強制性的,但建議使用,因為某些查詢需要依賴此標誌才能有效推送。
例如,當您在連線查詢中使用某些聚合、數學運算或資料類型轉換時,它會被轉換為 Presto 函式,並應用於 'join' 運算。 對於會產生中間 Presto 函式的任何「連結」查詢,連接器無法處理該查詢,因此不會執行下推。
範例 | 查詢 |
---|---|
對於建立 Presto 函式的查詢 | abs(int_clumn)=int_column2; int_sum_column=int_value1_column1+int_value1_column2 cast(varchar_20_column, varchar(100) )=varchar100_column |
驗證連線下推
若要檢查連線查詢是否已下推至底層資料來源,您可以檢查查詢的 EXPLAIN 計劃。
請考慮下列各點,以驗證連線查詢是否已下推至底層資料來源:
- 如果計劃沒有顯示「連結」操作員,表示發生了完整的推倒。
- 如果連線操作員的數目少於原始連線查詢的數目,表示發生了部分下推的情況。
- 如果連接操作員的數目與原始查詢相同,表示沒有發生 pushdown。
以下範例說明如何驗證連線下推的結果:
加入查詢:
SELECT order_id, c_customer_id FROM postgresql.public.orders o INNER JOIN postgresql.public.customer c ON c.c_customer_id=o.customer_id;
原始 Presto 計劃:
- Output[PlanNodeId 9][order_id, c_customer_id] => [order_id:integer, c_customer_id:char(16)]
- RemoteStreamingExchange[PlanNodeId 266][GATHER] => [order_id:integer, c_customer_id:char(16)]
- InnerJoin[PlanNodeId 4][(""customer_id"" = ""c_customer_id"")][$hashvalue, $hashvalue_11] => [order_id:integer, c_customer_id:char(16)]
Distribution: PARTITIONED
- RemoteStreamingExchange[PlanNodeId 264][REPARTITION][$hashvalue] => [customer_id:char(16), order_id:integer, $hashvalue:bigint]
Estimates: {source: CostBasedSourceInfo, rows: ? (?), cpu: ?, memory: 0.00, network: ?}
- ScanProject[PlanNodeId 0,326][table = TableHandle {connectorId='postgresql', connectorHandle='JdbcTableHandle{connectorId=postgresql, schemaTableName=public.orders, catalogName=null, schemaName=public, tableName=orders, joinTables=Optional.empty}', layout='Optional[{domains=ALL, additionalPredicate={}}]'}, projectLocality = LOCAL] => [customer_id:char(16), order_id:integer, $hashvalue_10:bigint]
Estimates: {source: CostBasedSourceInfo, rows: ? (?), cpu: ?, memory: 0.00, network: 0.00}/{source: CostBasedSourceInfo, rows: ? (?), cpu: ?, memory: 0.00, network: 0.00}
$hashvalue_10 := combine_hash(BIGINT'0', COALESCE($operator$hash_code(customer_id), BIGINT'0')) (3:6)
LAYOUT: {domains=ALL, additionalPredicate={}}
order_id := JdbcColumnHandle{connectorId=postgresql, columnName=order_id, jdbcTypeHandle=JdbcTypeHandle{jdbcType=4, jdbcTypeName=int4, columnSize=10, decimalDigits=0, arrayDimensions=null}, columnType=integer, nullable=true, comment=Optional.empty} (3:6)
customer_id := JdbcColumnHandle{connectorId=postgresql, columnName=customer_id, jdbcTypeHandle=JdbcTypeHandle{jdbcType=1, jdbcTypeName=bpchar, columnSize=16, decimalDigits=0, arrayDimensions=null}, columnType=char(16), nullable=true, comment=Optional.empty} (3:6)
- LocalExchange[PlanNodeId 297][HASH][$hashvalue_11] (c_customer_id) => [c_customer_id:char(16), $hashvalue_11:bigint]
Estimates: {source: CostBasedSourceInfo, rows: ? (?), cpu: ?, memory: 0.00, network: ?}
- RemoteStreamingExchange[PlanNodeId 265][REPARTITION][$hashvalue_12] => [c_customer_id:char(16), $hashvalue_12:bigint]
Estimates: {source: CostBasedSourceInfo, rows: ? (?), cpu: ?, memory: 0.00, network: ?}
- ScanProject[PlanNodeId 1,327][table = TableHandle {connectorId='postgresql', connectorHandle='JdbcTableHandle{connectorId=postgresql, schemaTableName=public.customer, catalogName=null, schemaName=public, tableName=customer, joinTables=Optional.empty}', layout='Optional[{domains=ALL, additionalPredicate={}}]'}, projectLocality = LOCAL] => [c_customer_id:char(16), $hashvalue_13:bigint]
Estimates: {source: CostBasedSourceInfo, rows: ? (?), cpu: ?, memory: 0.00, network: 0.00}/{source: CostBasedSourceInfo, rows: ? (?), cpu: ?, memory: 0.00, network: 0.00}
$hashvalue_13 := combine_hash(BIGINT'0', COALESCE($operator$hash_code(c_customer_id), BIGINT'0')) (4:12)
LAYOUT: {domains=ALL, additionalPredicate={}}
c_customer_id := JdbcColumnHandle{connectorId=postgresql, columnName=c_customer_id, jdbcTypeHandle=JdbcTypeHandle{jdbcType=1, jdbcTypeName=bpchar, columnSize=16, decimalDigits=0, arrayDimensions=null}, columnType=char(16), nullable=true, comment=Optional.empty} (4:12)
Pushdown Presto 計劃:
- Output[PlanNodeId 9][order_id, c_customer_id] => [order_id:integer, c_customer_id:char(16)]
Estimates: {source: CostBasedSourceInfo, rows: ? (?), cpu: ?, memory: 0.00, network: ?}
- RemoteStreamingExchange[PlanNodeId 261][GATHER] => [order_id:integer, c_customer_id:char(16)]
Estimates: {source: CostBasedSourceInfo, rows: ? (?), cpu: ?, memory: 0.00, network: ?}
- TableScan[PlanNodeId 287][TableHandle {connectorId='postgresql', connectorHandle='JdbcTableHandle{connectorId=postgresql, schemaTableName=public.orders, catalogName=null, schemaName=public, tableName=orders, joinTables=Optional[[JdbcTableHandle{connectorId=postgresql, schemaTableName=public.orders, catalogName=null, schemaName=public, tableName=orders, joinTables=Optional.empty}, JdbcTableHandle{connectorId=postgresql, schemaTableName=public.customer, catalogName=null, schemaName=public, tableName=customer, joinTables=Optional.empty}]]}', layout='Optional[{domains=ALL, additionalPredicate={}}]'}] => [customer_id:char(16), order_id:integer, c_customer_id:char(16)]
Estimates: {source: CostBasedSourceInfo, rows: ? (?), cpu: ?, memory: 0.00, network: 0.00}
LAYOUT: {domains=ALL, additionalPredicate={}}
c_customer_id := JdbcColumnHandle{connectorId=postgresql, columnName=c_customer_id, jdbcTypeHandle=JdbcTypeHandle{jdbcType=1, jdbcTypeName=bpchar, columnSize=16, decimalDigits=0, arrayDimensions=null}, columnType=char(16), nullable=true, comment=Optional.empty} (4:12)
customer_id := JdbcColumnHandle{connectorId=postgresql, columnName=customer_id, jdbcTypeHandle=JdbcTypeHandle{jdbcType=1, jdbcTypeName=bpchar, columnSize=16, decimalDigits=0, arrayDimensions=null}, columnType=char(16), nullable=true, comment=Optional.empty} (3:6)
order_id := JdbcColumnHandle{connectorId=postgresql, columnName=order_id, jdbcTypeHandle=JdbcTypeHandle{jdbcType=4, jdbcTypeName=int4, columnSize=10, decimalDigits=0, arrayDimensions=null}, columnType=integer, nullable=true, comment=Optional.empty} (3:6)
啟用 JDBC 加入下推的條件
JDBC join pushdown 可使查詢執行得更快,有時可快達 10 倍。 但是,必須小心使用。 如果使用不當,可能會導致查詢處理速度變慢。
以下是啟用 JDBC 加入下推的主要注意事項:
-
如果您只有有限數量的記錄,因為連接操作的結果來自巨大的資料表:
- 連接應該會從大型資料表中傳回一個相對較小的記錄子集。
- 理想的連接條件通常只會傳回總記錄的 10% 以下。
-
避免交叉接合:
- 如果連接條件會導致交叉連接結果,則不應使用連接下推功能。 交叉連接(產生兩個資料表的笛卡兒乘積)會降低效能。
-
資料庫最佳化:
- 資料庫系統應經過最佳化,以有效率地處理連線查詢,尤其是非等式連線。 Presto 能夠對等連接條件 (=) 和非等連接條件 (<, >, <=, >=,!=, <>) 執行連接下推。幾乎所有資料庫都能有效處理等連接。 但並非所有資料庫都針對非相連條件進行最佳化。
-
聚合:
- 只有選擇查詢會向下推送。 進行聚合的查詢 (例如 select count())不會被推下,可能會影響效能。
隨著資料表行數的增加,以及連接結果限制在總記錄的 10% 以下,您可以看到效能的提升。 請參閱下列統計資料以瞭解其行為:
結合查詢 | 結合查詢 | 效能提升 |
---|---|---|
select A.ASSIGNMENT_ID, A.ROLE, A.IS_CURRENT, B.ASSIGNMENT_ID, B.DEFAULT_INT from DB2.DB2.ASSIGNMENTS a join DB2.DB2.STUDENT b on A.ASSIGNMENT_ID = B.ASSIGNMENT_ID; |
連接資料表時: ASSIGNMENTS 有 1000 萬行, STUDENT 有 5000 行 Join 結果是 50 行。 |
5x |
select A.ASSIGNMENT_ID, A.ROLE, A.IS_CURRENT, B.ASSIGNMENT_ID, B.DEFAULT_INT from DB2.DB2.ASSIGNMENTS a join DB2.DB2.STUDENT b on A.ASSIGNMENT_ID = B.ASSIGNMENT_ID; |
連接資料表時: ASSIGNMENTS 有 2,000 萬行,而 STUDENT 有 5,000 行 Join 結果是 50 行。 |
10x |
表中顯示的統計資料只是一個近似的範例,根據資料庫和環境的不同,數值有可能會有所差異。
支援連線下推的資料類型和運算符號
下列資料類型和運算符號支援連線下推功能:
資料類型 | 運算子 |
---|---|
BigInt | =, <, >, <=, >=,!= 和 <> |
布林 | =, !=, <> |
整數 | =, <, >, <=, >=,!= 和 <> |
TINYINT | =, <, >, <=, >=,!= 和 <> |
SMALLINT | =, <, >, <=, >=,!= 和 <> |
浮點 | =, <, >, <=, >=,!= 和 <> |
REAL | =, <, >, <=, >=,!= 和 <> |
DOUBLE | =, <, >, <=, >=,!= 和 <> |
DECIMAL | =, <, >, <=, >=,!= 和 <> |
VARCHAR | =, <, >, <=, >=,!= 和 <> |
字元 | =, <, >, <=, >=,!= 和 <> |
聯邦連線下推
聯合連接是包含來自多個目錄的資料表的連接查詢。
在聯結連接中,Presto 根據 JDBC 目錄將資料表分組,以優化 pushdown。 然而,只有在下列情況下才有可能推倒:
- JDBC 資料來源:表格來自 資料來源。JDBC
- 推倒規格:連接作業符合推倒的特定要求,例如相容的資料類型和操作員。 如需詳細資訊,請參閱 Presto JDBC 資料來源中 Join 查詢下推的主要注意事項。
如果資料表不符合這些條件,則會從 pushdown 中排除,並直接由 Presto 處理。 下表顯示聯結加入的範例:
聯盟加盟 |
---|
選擇i1.customer_last_name, A.ASSIGNMENT_ID, B.FIRST_NAME, t2.custkey FROMDB2_CATALOG.DB2.ASSIGNMENTS_10_MILLION A JOINDB2_CATALOG.DB2.CUSTOMER_10_MILLION BONA.EMPLOYEE_ID = B.CUST_ID JOINDB2_CATALOG.DB2.JOIN_TABLE_50_ROWS CONA.ASSIGNMENT_ID = C.ASSIGNMENT_ID JOINpostgres_catalog.pg.customer t1onB.CUST_ID = t1.custkey Joinpostgres_catalog.pg.orders t2ONt1.custkey = t2.orderkey Joinpostgres_catalog.pg.products t3ONt3.productkey = t2.productkey JOINiceberg_catalog.ice.customer i1ONi1.customer = B.CUST_ID |
這裡,查詢有 3 個目錄,分別是 db2_catalog, postgres_catalog 和 iceberg_catalog。 db2_catalog ( db2 目錄) 有 3 個表 postgres_catalog (postgres 目錄) 有 3 個表 iceberg_catalog (iceberg 目錄) 有 1 個表 |
對於前面的聯合加入查詢,join pushdown 優化器為目錄 db2_catalog 和 posgres_catalog 建立 Join Operation,如下表所示。 由於 iceberg_catalog 不是 JDBC 資料來源,因此會跳過,並返回 Presto 進行處理。
欄位 | 說明 |
---|---|
DB2_CATALOG 連結優化器所建立的連結操作表示法 |
Select t2.custkey From DB2_CATALOG.DB2.ASSIGNMENTS_10_MILLION A, DB2_CATALOG.DB2.CUSTOMER_10_MILLION B, DB2_CATALOG.DB2.JOIN_TABLE_50_ROWS C where A.EMPLOYEE_ID = B.CUST_ID and A.ASSIGNMENT_ID = C.ASSIGNMENT_ID; |
posgres_catalog 連結作業的表示方式 連結推倒最佳化器建立 |
Select A.ASSIGNMENT_ID, B.FIRST_NAME From posgres_catalog.pg.customer t1, posgres_catalog.pg.orders t2, posgres_catalog.pg.products t3 where t1.custkey = t2.orderkey and t3.productkey = t2.productkey; |
經過連線下推的最佳化之後,前面的聯合查詢由 Presto 處理如下:
select i1.customer_last_name, A.ASSIGNMENT_ID, B.FIRST_NAME, t2.custkey from (result of DB2_CATALOG Join pushdown) join ( result of posgres_catalog Join pushdown) on B.CUST_ID = t1.custkey join iceberg_catalog.ice.customer i1ONi1.customer = B.CUST_ID
支援連線下推的資料來源清單
下列資料來源支援連線下推功能:
- IBM Db2
- PostgreSQL
- Informix
- IBM Netezza
- MySQL
- Oracle
- SQL Server
- Teradata
- Amazon Redshift
- SingleStore
- Snowflake
- HANA
- Apache Phoenix
接合下壓的好處
以下是加入 pushdown 功能的優點:
- 改善整體查詢效能。
- 減少 IBM presto 與資料來源之間的網路流量。
- 降低遠端資料來源的負載。
- 由於命中的資料庫數量有限,因此可大幅降低成本。
連線下推的限制
以下是加入下推功能的限制:
- 依賴於篩選推送:Join pushdown 依賴於底層資料庫現有的 filter pushdown 功能。 篩選器推送的任何限制或低效率都會影響連接推送的效能。
- 資料庫相容性:Join pushdown 只限於底層資料庫可以理解的查詢。 涉及篩選器、投射、條件或特殊關鍵字的複雜查詢可能無法向下推送。
- 自結限制:目前 Self-Join 的實作並非最佳,而且對表句柄快取記憶體有依賴。 根據預設,表句柄快取在 Presto 中是關閉的,如果啟用,則自連結推倒會失敗。
在使用者介面檢視 JDBC Pushdown 功能
- 登入 watsonx.data 範例。
- 前往組態。
- 按一下 JDBC 下拉式磁磚。 畫面上會出現 JDBC pushdown 詳細資訊頁面。
- 按一下說明文件連結,以瞭解 watsonx.data 中 JDBC pushdown 功能的更多資訊。