使用 YAML 轉換 SQL 翻譯
本文說明如何使用 YAML 設定檔,在將 SQL 程式碼遷移至 BigQuery 時轉換該程式碼。本指南說明如何建立自己的設定 YAML 檔案,並提供這項功能支援的各種翻譯轉換範例。
使用 BigQuery 互動式 SQL 翻譯器、BigQuery Migration API 或執行批次 SQL 翻譯時,您可以提供 YAML 設定檔來修改 SQL 查詢翻譯。使用 YAML 設定檔,即可進一步自訂來源資料庫的 SQL 查詢轉譯作業。
您可以透過下列方式,指定要在 SQL 轉譯中使用的設定 YAML 檔案:
- 如果您使用的是互動式 SQL 轉譯器,請在轉譯設定中指定設定檔的路徑或批次轉譯工作 ID。
- 如果您要執行批次 SQL 翻譯,或使用 BigQuery Migration API,請將 YAML 設定檔放在與輸入 SQL 檔案相同的 Cloud Storage bucket。
互動式 SQL 翻譯器、BigQuery Migration API 和批次 SQL 翻譯器,都支援在單一翻譯工作中使用多個 YAML 設定檔。詳情請參閱「套用多個 YAML 設定」。
設定 YAML 檔案規定
建立 YAML 設定檔前,請先詳閱下列資訊,確保 YAML 檔案與 BigQuery 遷移服務相容:
- 您必須將設定 YAML 檔案上傳至 Cloud Storage bucket 的目錄,其中包含 SQL 轉譯輸入檔案。如要瞭解如何建立 bucket 並將檔案上傳至 Cloud Storage,請參閱「建立 bucket」和「從檔案系統上傳物件」。
- 單一設定 YAML 檔案的大小不得超過 1 MB。
- 單一 SQL 翻譯工作中使用的所有設定 YAML 檔案,總大小不得超過 4 MB。
- 如果您使用
regex語法進行名稱比對,請使用 RE2/J。 - 所有設定 YAML 檔案名稱都必須包含
.config.yaml副檔名,例如change-case.config.yaml。config.yaml不是有效的設定檔名稱。
建立 YAML 設定檔的操作說明
本節提供建立設定 YAML 檔案的一般指南:
標頭
每個設定檔都必須包含指定設定類型的標頭。object_rewriter 類型用於在設定 YAML 檔案中指定 SQL 翻譯。以下範例使用 object_rewriter 類型轉換名稱大小寫:
type: object_rewriter
global:
case:
all: UPPERCASE
實體選取
如要執行實體專屬轉換,請在設定檔中指定實體。所有 match 屬性皆為選用,請只使用轉換所需的 match 屬性。下列設定 YAML 會公開要比對的屬性,以便選取特定實體:
match:
database: <literal_name>
schema: <literal_name>
relation: <literal_name>
attribute: <literal_name>
databaseRegex: <regex>
schemaRegex: <regex>
relationRegex: <regex>
attributeRegex: <regex>
各項 match 屬性的說明:
database或db:project_id 元件。schema:資料集元件。relation:表格元件。attribute:資料欄元件。僅適用於屬性選取databaseRegex或dbRegex:使用規則運算式比對database屬性 (預先發布版)。schemaRegex:比對schema屬性與規則運算式 (預先發布版)。relationRegex:使用規則運算式比對relation屬性 (預先發布版)。attributeRegex:使用規則運算式比對attribute屬性。僅適用於屬性選取 (預先發布版)。
舉例來說,下列設定 YAML 會指定 match 屬性,選取 testdb.acme.employee 資料表進行臨時資料表轉換。
type: object_rewriter
relation:
-
match:
database: testdb
schema: acme
relation: employee
temporary: true
您可以使用 databaseRegex、schemaRegex、relationRegex 和 attributeRegex 屬性指定規則運算式,選取實體子集。以下範例會將 testdb 中 tmp_schema 架構的所有關係變更為暫時關係,只要名稱開頭為 tmp_ 即可:
type: object_rewriter
relation:
-
match:
schema: tmp_schema
relationRegex: "tmp_.*"
temporary: true
常值和 regex 屬性都不區分大小寫。您可以使用 regex 搭配停用的 i 旗標,強制執行區分大小寫的比對,如以下範例所示:
match:
relationRegex: "(?-i:<actual_regex>)"
您也可以使用等效的短字串語法,指定完整實體。短字串語法應包含 3 個 (用於選取關係) 或 4 個 (用於選取屬性) 名稱區段,並以點分隔,例如 testdb.acme.employee。接著,系統會將這些區隔解讀為分別以 database、schema、relation 和 attribute 傳遞。這表示名稱會逐字比對,因此簡短語法不允許使用規則運算式。以下範例說明如何使用短字串語法,在設定 YAML 檔案中指定完整實體:
type: object_rewriter
relation:
-
match : "testdb.acme.employee"
temporary: true
如果資料表名稱包含點號,則無法使用簡短語法指定名稱。在這種情況下,您必須使用物件比對。以下範例會將 testdb.acme.stg.employee 資料表變更為臨時資料表:
type: object_rewriter
relation:
-
match:
database: testdb
schema: acme
relation: stg.employee
temporary: true
設定 YAML 接受 key 做為 match 的別名。
預設資料庫
部分輸入 SQL 方言 (尤其是 Teradata) 不支援在完整名稱中使用 database-name。在這種情況下,比對實體最簡單的方法是省略 match 中的 database 屬性。
不過,您可以設定 BigQuery Migration Service 的 default_database 屬性,並在 match 中使用該預設資料庫。
支援的目標屬性類型
您可以使用 YAML 設定檔執行屬性類型轉換,將資料欄的資料類型從來源類型轉換為目標類型。設定 YAML 檔案支援下列指定類型:
BOOLEANTINYINTSMALLINTINTEGERBIGINTFLOATDOUBLENUMERIC(支援選用的精確度和規模,例如NUMERIC(18, 2))TIMETIMETZDATEDATETIMETIMESTAMPTIMESTAMPTZCHAR(支援選用精確度,例如CHAR(42))VARCHAR(支援選用精確度,例如VARCHAR(42))
設定 YAML 範例
本節提供範例,說明如何建立各種設定 YAML 檔案,以便與 SQL 翻譯搭配使用。每個範例都會列出 YAML 語法,說明如何以特定方式轉換 SQL 翻譯,並附上簡短說明。每個範例也提供 teradata-input.sql 或 hive-input.sql 檔案和 bq-output.sql 檔案的內容,方便您比較 YAML 設定對 BigQuery SQL 查詢翻譯的影響。
下列範例使用 Teradata 或 Apache Hive 做為輸入 SQL 方言,並使用 BigQuery SQL 做為輸出方言。下列範例也使用 testdb 做為預設資料庫,並使用 testschema 做為結構定義搜尋路徑。
變更物件名稱大小寫
下列設定 YAML 會變更物件名稱的大小寫:
type: object_rewriter
global:
case:
all: UPPERCASE
database: LOWERCASE
attribute: LOWERCASE
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(a int); select * from x; |
bq-output.sql |
CREATE TABLE testdb.TESTSCHEMA.X ( a INT64 ) ; SELECT X.a FROM testdb.TESTSCHEMA.X ; |
將資料表設為臨時資料表
下列設定 YAML 會將一般資料表變更為臨時資料表:
type: object_rewriter
relation:
-
match: "testdb.testschema.x"
temporary: true
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(a int); |
bq-output.sql |
CREATE TEMPORARY TABLE x ( a INT64 ) ; |
將資料表設為臨時
下列設定 YAML 會將一般資料表變更為臨時資料表,並在 60 秒後到期。
type: object_rewriter
relation:
-
match: "testdb.testschema.x"
ephemeral:
expireAfterSeconds: 60
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(a int); |
bq-output.sql |
CREATE TABLE testdb.testschema.x ( a INT64 ) OPTIONS( expiration_timestamp=timestamp_add(current_timestamp(), interval 60 SECOND) ); |
設定分區到期時間
下列設定 YAML 會將分區資料表的到期時間變更為 1 天:
type: object_rewriter
relation:
-
match: "testdb.testschema.x"
partitionLifetime:
expireAfterSeconds: 86400
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(a int, b int) partition by (a); |
bq-output.sql |
CREATE TABLE testdb.testschema.x ( a INT64, b INT64 ) CLUSTER BY a OPTIONS( partition_expiration_days=1 ); |
變更資料表的外部位置或格式
下列設定 YAML 會變更資料表的外部位置和格式:
type: object_rewriter
relation:
-
match: "testdb.testschema.x"
external:
locations: "gs://path/to/department/files"
format: ORC
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(a int); |
bq-output.sql |
CREATE EXTERNAL TABLE testdb.testschema.x ( a INT64 ) OPTIONS( format='ORC', uris=[ 'gs://path/to/department/files' ] ); |
設定或變更資料表說明
下列設定 YAML 會設定資料表的說明:
type: object_rewriter
relation:
-
match: "testdb.testschema.x"
description:
text: "Example description."
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(a int); |
bq-output.sql |
CREATE TABLE testdb.testschema.x ( a INT64 ) OPTIONS( description='Example description.' ); |
設定或變更資料表分區
下列設定 YAML 會變更資料表的分區配置,以便依日期資料欄分區:
type: object_rewriter
relation:
-
match: "testdb.testschema.x"
partition:
simple:
add: [a]
-
match: "testdb.testschema.y"
partition:
simple:
remove: [a]
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(a date, b int); create table y(a date, b int) partition by (a); |
bq-output.sql |
CREATE TABLE testdb.testschema.x ( a DATE, b INT64 ) PARTITION BY a; CREATE TABLE testdb.testschema.y ( a DATE, b INT64 ) ; |
下列設定 YAML 會變更資料表的分區配置,依範圍 bucket 分區:
type: object_rewriter
relation:
-
key: "testdb.testschema.mytable"
partition:
range_bucket:
column: "id"
start: 0
end: 100
step: 10
options:
require_partition_filter: "TRUE"
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
snowflake-input.sql |
create table testschema.mytable (date timestamp_ntz, id number, content variant); |
bq-output.sql |
create table testdb.testschema.mytable ( date datetime, id int64, content json ) partition by range_bucket(id, generate_array(0, 100, 10)) options( require_partition_filter=true ); |
設定或變更資料表分群
下列設定 YAML 會變更資料表的叢集配置:
type: object_rewriter
relation:
-
match: "testdb.testschema.x"
clustering:
add: [a]
-
match: "testdb.testschema.y"
clustering:
remove: [b]
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
hive-input.sql |
create table x(a int, b int); create table y(a int, b int) clustered by (b) into 16 buckets; |
bq-output.sql |
CREATE TABLE testdb.testschema.x ( a INT64, b INT64 ) CLUSTER BY a; CREATE TABLE testdb.testschema.y ( a INT64, b INT64 ) ; |
變更資料欄屬性的類型
下列設定 YAML 會變更資料欄屬性的資料類型:
type: object_rewriter
attribute:
-
match:
database: testdb
schema: testschema
attributeRegex: "a+"
type:
target: NUMERIC(10,2)
您可以將來源資料類型轉換為任何支援的目標屬性類型。
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(a int, b int, aa int); |
bq-output.sql |
CREATE TABLE testdb.testschema.x ( a NUMERIC(31, 2), b INT64, aa NUMERIC(31, 2) ) ; |
新增外部資料湖泊連線
下列設定 YAML 會將來源資料表標示為外部資料表,指向儲存在外部資料湖泊中的資料,並由資料湖泊連線指定。
type: object_rewriter
relation:
-
key: "testdb.acme.employee"
external:
connection_id: "connection_test"
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
hive-input.sql |
CREATE TABLE x ( a VARCHAR(150), b INT ); |
bq-output.sql |
CREATE EXTERNAL TABLE x ( a STRING, b INT64 ) WITH CONNECTION `connection_test` OPTIONS( ); |
變更輸入檔案的字元編碼
根據預設,BigQuery 移轉服務會嘗試自動偵測輸入檔案的字元編碼。如果 BigQuery 移轉服務可能誤判檔案編碼,您可以使用 YAML 設定檔明確指定字元編碼。
下列設定 YAML 將輸入檔案的明確字元編碼指定為 ISO-8859-1。
type: experimental_input_formats
formats:
- source:
pathGlob: "*.sql"
contents:
raw:
charset: iso-8859-1
全域類型轉換
下列設定 YAML 會在所有指令碼中將資料類型變更為另一種,並指定要在轉譯指令碼中避免的來源資料類型。這與「變更資料欄屬性的類型」設定不同,後者只會變更單一屬性的資料類型。
BigQuery 支援下列資料類型轉換:
DATETIME至TIMESTAMPTIMESTAMP到DATETIME(可選填時區)TIMESTAMP WITH TIME ZONE到DATETIME(可選填時區)CHAR至VARCHAR
在以下範例中,設定 YAML 會將 TIMESTAMP 資料類型轉換為 DATETIME。
type: experimental_object_rewriter
global:
typeConvert:
timestamp: DATETIME
設定預設時區
資料庫方言對不同的日期和時間相關資料類型,有不同的語意和名稱。無論輸入方言的資料類型名稱為何,翻譯服務都會在 YAML 設定中標準化下列術語:
datetime是Y-M-D H:M:S的組合,不固定在任何特定時區。datetime代表時鐘時間,而非特定時間點。timestamp代表特定或絕對時間點,因此會隱含固定在特定時區,這可能是工作階段層級或資料庫設定。timestamptz代表特定時間點,例如timestamp,但與timestamp不同的是,它會帶有特定時區偏移。雖然2019-06-01 12:00:00+4和2019-06-01 06:00:00-2代表相同的時間點,但系統會將兩者視為不同的timestamptz值。
在 Teradata 等方言中,current_date、current_time 或 current_timestamp 等日期時間相關函式會根據隱含設定的工作階段時區參數傳回時間戳記。BigQuery 則一律會傳回世界標準時間 (UTC) 的時間戳記。為確保兩種方言的行為一致,可能需要相應設定時區。
如果來源資料庫的預設時區不是世界標準時間,建議您指定翻譯的預設時區。這樣可保留時區,確保翻譯後的查詢能正確運作。
在以下範例中,YAML 設定會將 TIMESTAMP 和 TIMESTAMPTZ 資料類型轉換為 DATETIME,並將目標時區設為 Europe/Paris。
如要瞭解有效的字串時區值,請參閱「時區」。
type: experimental_object_rewriter
global:
typeConvert:
timestamp:
target: DATETIME
timezone: Europe/Paris
timestamptz:
target: DATETIME
timezone: Europe/Paris
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
snowflake-input.sql |
create table x(c_timestamp timestamp_ltz, c_timestamptz timestamp_tz, c_datetime timestamp_ntz); select c_timestamp from x where c_timestamp > current_timestamp(0); select c_timestamptz from x where c_timestamptz > cast(current_timestamp(0) as timestamp_tz); select c_datetime from x where c_datetime > cast(current_timestamp(0) as timestamp_ntz); |
bq-output.sql |
CREATE TABLE x ( c_timestamp DATETIME, c_timestamptz DATETIME, c_datetime DATETIME ) ; SELECT x.c_timestamp FROM test.x WHERE x.c_timestamp > datetime(current_timestamp(), 'Europe/Paris') ; SELECT x.c_timestamptz FROM test.x WHERE x.c_timestamptz > datetime(current_timestamp(), 'Europe/Paris') ; SELECT x.c_datetime FROM test.x WHERE x.c_datetime > datetime(current_timestamp(), 'Europe/Paris') ; |
在以下範例中,設定 YAML 會將 DATETIME 資料類型轉換為 TIMESTAMP。
根據預設,TIMESTAMPTZ 會轉換為 TIMESTAMP,不需設定。
type: experimental_object_rewriter
global:
typeConvert:
datetime:
target: TIMESTAMP
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
snowflake-input.sql |
create table x(c_timestamp timestamp_ltz, c_timestamptz timestamp_tz, c_datetime timestamp_ntz); select c_timestamp from x where c_timestamp > current_timestamp(0); select c_timestamptz from x where c_timestamptz > cast(current_timestamp(0) as timestamp_tz); select c_datetime from x where c_datetime > cast(current_timestamp(0) as timestamp_ntz); |
bq-output.sql |
CREATE TABLE x ( c_timestamp TIMESTAMP, c_timestamptz TIMESTAMP, c_datetime TIMESTAMP ) ; SELECT x.c_timestamp FROM test.x WHERE x.c_timestamp > current_timestamp() ; SELECT x.c_timestamptz FROM test.x WHERE x.c_timestamptz > current_timestamp() ; SELECT x.c_datetime FROM test.x WHERE x.c_datetime > current_timestamp() ; |
選取對帳單修改
下列設定 YAML 會變更 SELECT 陳述式中的星號投影、GROUP BY 和 ORDER BY 子句。
starProjection 支援下列設定:
ALLOWPRESERVE(預設)EXPAND
groupBy 和 orderBy 支援下列設定:
EXPRESSIONALIASINDEX
在以下範例中,設定 YAML 會將星號投影設為 EXPAND。
type: experimental_statement_rewriter
select:
starProjection: EXPAND
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(a int, b TIMESTAMP); select * from x; |
bq-output.sql |
CREATE TABLE x ( a INT64, b DATETIME ) ; SELECT x.a x.b FROM x ; |
UDF 規格
在多數情況下,即使 UDF 主體是以外部語言編寫,BigQuery SQL 翻譯工具也能自動剖析外部 user-defined function (UDF) 的資料定義語言 (DDL),判斷其輸入和輸出資料類型。不過,對於某些來源方言,翻譯工具可能無法自動編譯 UDF 簽章。為確保參照這些 UDF 的 SQL 陳述式能準確翻譯,且不必提供原始 DDL,您可以使用 YAML 設定檔明確註冊 UDF 簽章。
下列設定 YAML 會指定來源指令碼中使用的 user-defined function (UDF) 簽章。與中繼資料 ZIP 檔案類似,UDF 定義有助於更準確地翻譯輸入指令碼。
type: metadata
udfs:
- "date parse_short_date(dt int)"
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(dt int); select parse_short_date(dt) + 1 from x; |
bq-output.sql |
CREATE TABLE x ( dt INT64 ) ; SELECT date_add(parse_short_date(x.dt), interval 1 DAY) FROM x ; |
設定小數位數嚴格程度
根據預設,BigQuery 遷移服務會將數值精確度提高至指定小數位數可用的最高精確度。下列設定 YAML 會將精確度嚴格程度設為保留來源陳述式的小數精確度,藉此覆寫這項行為。
type: experimental_statement_rewriter
common:
decimalPrecision: STRICT
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(a decimal(3,0)); |
bq-output.sql |
CREATE TABLE x ( a NUMERIC(3) ) ; |
設定字串精確度嚴格程度
根據預設,BigQuery 遷移服務在翻譯 CHAR 和 VARCHAR 資料欄時,會省略字串精確度。這有助於避免在寫入值時發生截斷錯誤。部分 SQL 方言 (例如 Teradata) 會截斷超過寫入時最大精確度的值,而 BigQuery 在這種情況下會傳回錯誤。
如果應用程式不依賴來源方言的截斷行為,請考慮在翻譯後的類型定義中保留資料欄的精確度。
下列設定 YAML 會覆寫這項行為,方法是設定精確度嚴格程度,保留來源陳述式的字串精確度。
type: experimental_statement_rewriter
common:
stringPrecision: STRICT
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table x(a varchar(3)); |
bq-output.sql |
CREATE TABLE x ( a STRING(3) ) ; |
輸出名稱對應
您可以使用設定 YAML 對應 SQL 物件名稱。您可以根據對應的物件,變更名稱的不同部分。
靜態名稱對應
使用靜態名稱對應,對應實體的名稱。如果只想變更名稱的特定部分,其他部分保持不變,則只需加入需要變更的部分。
下列設定 YAML 會將資料表名稱從 my_db.my_schema.my_table 變更為 my_new_db.my_schema.my_new_table。
type: experimental_object_rewriter
relation:
-
match: "my_db.my_schema.my_table"
outputName:
database: "my_new_db"
relation: "my_new_table"
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table my_db.my_schema.my_table(a int); |
bq-output.sql |
CREATE TABLE my_new_db.my_schema.my_new_table ( a INT64 ) |
您可以使用靜態名稱對應,更新公開使用者定義函式中名稱使用的區域。
以下範例會將 bqutil.fn UDF 中的名稱,從使用預設的 us 多區域,變更為使用 europe_west2 區域:
type: experimental_object_rewriter
function:
-
match:
database: bqutil
schema: fn
outputName:
database: bqutil
schema: fn_europe_west2
動態名稱對應
使用動態名稱對應功能,可同時變更多個物件,並根據對應的物件建立新名稱。
下列設定 YAML 會將前置字串 stg_ 新增至屬於 staging 結構定義的資料表,然後將這些資料表移至 production 結構定義,藉此變更所有資料表的名稱。
type: experimental_object_rewriter
relation:
-
match:
schema: staging
outputName:
schema: production
relation: "stg_${relation}"
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table staging.my_table(a int); |
bq-output.sql |
CREATE TABLE production.stg_my_table ( a INT64 ) ; |
指定預設資料庫和結構定義搜尋路徑
type: environment
session:
defaultDatabase: myproject
schemaSearchPath: [myschema1, myschema2]
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
SELECT * FROM database.table SELECT * FROM table1 |
bq-output.sql |
SELECT * FROM myproject.database.table. SELECT * FROM myproject.myschema1.table1 |
設定 NLS_DATE_FORMAT
下列設定 YAML 會將 NLS_DATE_FORMAT 參數設為 DD/MM/YYYY 格式。建議您指定 NLS_DATE_FORMAT,以隱含方式使用日期格式和轉換。如未設定,系統會使用預設的翻譯格式 DD-MON-RR。
type: environment
session:
dateFormat: DD/MM/YYYY
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
oracle-input.sql |
create table x(dt date default '31/12/1999'); insert into x values ('01/01/2000'); |
bq-output.sql |
CREATE TABLE testdb.testschema.x ( DT DATETIME DEFAULT DATETIME '1999-12-31 00:00:00' ) ; INSERT INTO testdb.testschema.x (DT) VALUES (DATETIME '2000-01-01 00:00:00') ; |
全域輸出名稱重寫
下列設定 YAML 會根據設定的規則,變更指令碼中所有物件 (資料庫、結構定義、關係和屬性) 的輸出名稱。
type: experimental_object_rewriter
global:
outputName:
regex:
- match: '\s'
replaceWith: '_'
- match: '>='
replaceWith: 'gte'
- match: '^[^a-zA-Z_].*'
replaceWith: '_$0'
使用這個設定 YAML 檔案的 SQL 轉譯可能如下所示:
teradata-input.sql |
create table "test special chars >= 12"("42eid" int, "custom column" varchar(10)); |
bq-output.sql |
CREATE TABLE test_special_chars_employees_gte_12 ( _42eid INT64, custom_column STRING ) ; |
最佳化及提升翻譯 SQL 的效能
您可以對翻譯後的 SQL 套用選用轉換,藉此導入可改善效能或成本的變更。這些最佳化措施完全取決於個案,應與未修改的 SQL 輸出進行評估,以評估其對效能的實際影響。
下列設定 YAML 會啟用選用轉換。設定接受最佳化清單,以及接受參數的最佳化,以及含有選用參數值的部分。
type: optimizer
transformations:
- name: PRECOMPUTE_INDEPENDENT_SUBSELECTS
- name: REWRITE_CTE_TO_TEMP_TABLE
parameters:
threshold: 1
| 最佳化 | 選用參數 | 說明 |
|---|---|---|
PRECOMPUTE_INDEPENDENT_SUBSELECTS |
scope: [PREDICATE, PROJECTION]
|
新增 DECLARE 陳述式來重寫查詢,將 PREDICATE 子句或 PROJECTION 中的運算式替換為預先計算的變數。這會被視為靜態述詞,可減少讀取的資料量。如果省略範圍,預設值為 PREDICATE (即 WHERE 和 JOIN-ON 子句)。將純量子查詢擷取至 DECLARE 陳述式,會使原始述詞變成靜態,因此能改善執行計畫。這項最佳化作業會導入新的 SQL 陳述式。
|
REWRITE_CTE_TO_TEMP_TABLE |
threshold: N
|
如果對相同一般資料表運算式 (CTE) 的參照超過 N 個,則將 CTE 重新編寫為臨時資料表。這可降低查詢複雜度,並強制執行一般資料表運算式一次。如果省略 N,預設值為 4。如果多次參照非一般 CTE,建議使用這項最佳化功能。 導入臨時資料表會產生額外負擔,可能比最終多次執行低複雜度或低基數 CTE 的負擔更大。這項最佳化作業會導入新的 SQL 陳述式。 |
REWRITE_ZERO_SCALE_NUMERIC_AS_INTEGER |
bigint: N
|
如果精確度在 N 內,則將零刻度 NUMERIC/BIGNUMERIC 屬性重寫為 INT64 類型。如果省略 N,預設值為 18。如果來源方言沒有整數類型,建議您在翻譯時使用這項最佳化功能。變更資料欄類型時,必須檢查所有下游用途,確認類型相容性和語意變更。例如,分數除法變成整數除法,或程式碼預期數值。 Snowflake 翻譯預設會啟用這項最佳化功能,適用於精確度不超過 38 的零小數位數值。這項最佳化功能可確保 Snowflake INTEGER (在 Snowflake 中隱含表示為 NUMBER(38,0)) 會轉譯為 BigQuery INT64,而非 BIGNUMERIC(38)。如果應用程式使用的數字精確度超過 18,建議您停用這項功能,確保 BigQuery 能處理應用程式所需的完整值範圍。 |
DROP_TEMP_TABLE |
為指令碼中建立的所有暫存資料表新增 DROP TABLE 陳述式,且不會在指令碼結束時捨棄。這樣一來,臨時資料表的儲存空間計費週期就會從 24 小時縮短為指令碼執行時間。這項最佳化作業會導入新的 SQL 陳述式。如果指令碼執行完畢後,不會再存取臨時資料表進行任何進一步處理,建議使用這項最佳化功能。這項最佳化作業會導入新的 SQL 陳述式。 |
|
REGEXP_CONTAINS_TO_LIKE |
將部分類別的 REGEXP_CONTAINS 比對模式重寫為 LIKE 運算式。如果沒有其他程序 (例如巨集替換) 依賴輸出 SQL 中保持不變的規則運算式模式常值,建議使用這項最佳化功能。 |
|
ADD_DISTINCT_TO_SUBQUERY_IN_SET_COMPARISON |
將 DISTINCT 子句新增至子查詢,做為 [NOT] IN 運算子的值組合。如果子查詢結果的基數 (不重複值的數量) 遠低於值的數量,建議使用這項最佳化功能。如果未滿足這項前提條件,這項轉換可能會對效能造成負面影響。 |
|
APPROXIMATE_RANGE_PARTITIONS |
將非連續或非常規整數分區配置,轉換為 BigQuery 支援的連續等大小分區範圍,藉此近似這些配置。根據預設,這類分區配置不會影響翻譯 DDL 陳述式中的資料表分區配置。 如果來源資料表使用非連續分區函式 (例如 Teradata RANGE_N 函式),且 BigQuery 中大小相等的分區配置有助於提升效能,建議您使用這項最佳化功能。
|
最佳化示例
下列最佳化作業會將精確度小於或等於 38 的零小數位數數值類型,轉換為 BigQuery 中的 INT64。
# An INTEGER is internally represented as NUMBER(38,0) in Snowflake.
# To convert Snowflake INTEGER to INT64 in BigQuery, enable the rewrite for precision <= 38.
# Note that this can produce incorrect results if your application logic uses more than 18 digits of precision.
#
# This configuration is enabled by default for the Snowflake Dialect.
type: optimizer
transformations:
- name: REWRITE_ZERO_SCALE_NUMERIC_AS_INTEGER
parameters:
bigint: 38
經過這項最佳化後,SQL 翻譯可能如下所示:
snowflake-input.sql |
CREATE TABLE numbers(i INTEGER, n NUMERIC(10,0)); |
bq-output.sql |
CREATE TABLE numbers(i INT64, n INT64); |
下列設定會停用方言的最佳化功能,例如 Snowflake,預設為啟用。這項設定會根據輸入精確度,將數值類型轉換為 NUMERIC 或 BIGNUMERIC,而非預設的 INT64。
type: optimizer
transformations:
- name: REWRITE_ZERO_SCALE_NUMERIC_AS_INTEGER
enabled: false
經過這項最佳化後,SQL 翻譯可能如下所示:
snowflake-input.sql |
CREATE TABLE numbers(i INTEGER, n NUMERIC(10,0)); |
bq-output.sql |
CREATE TABLE numbers(i BIGNUMERIC(38), n NUMERIC(29)); |
建立以 Gemini 為基礎的設定 YAML 檔案
如要生成 AI 輸出內容,SQL 轉譯輸入內容的來源目錄必須包含設定 YAML 檔案。
需求條件
AI 輸出的設定 YAML 檔案必須有 .ai_config.yaml 後置字串。例如:rules_1.ai_config.yaml。
支援的欄位
您可以使用下列欄位設定 AI 翻譯輸出內容:
suggestion_type(選用):指定要生成的 AI 建議類型。支援的建議類型如下:QUERY_CUSTOMIZATION(預設):根據設定 YAML 檔案中指定的轉譯規則,生成 SQL 程式碼的 AI 建議。TRANSLATION_EXPLANATION:生成文字,其中包含翻譯後的 GoogleSQL 查詢摘要,以及來源 SQL 查詢與翻譯後的 GoogleSQL 查詢之間的差異和不一致之處。
rewrite_target(選用):如要將翻譯規則套用至輸入 SQL,請指定SOURCE_SQL;如要將翻譯規則套用至輸出 SQL,請指定TARGET_SQL(預設)。instruction(選用):以自然語言描述目標 SQL 的變更。Gemini 強化版 SQL 翻譯會評估要求,並進行指定變更。examples(選用):提供 SQL 範例,說明要如何修改 SQL 模式。
您可以視需要新增其他 translation_rules 和 examples。
範例
下列範例會建立 Gemini 專用的 YAML 設定檔,可用於 SQL 轉譯。
移除預設翻譯輸出查詢中的 upper 函式
translation_rules:
- instruction: "Remove upper() function"
examples:
- input: "upper(X)"
output: "X"
建立多項翻譯規則,自訂翻譯輸出內容
translation_rules:
- instruction: "Remove upper() function"
suggestion_type: QUERY_CUSTOMIZATION
rewrite_target: TARGET_SQL
examples:
- input: "upper(X)"
output: "X"
- instruction: "Insert a comment at the head that explains each statement in detail.
suggestion_type: QUERY_CUSTOMIZATION
rewrite_target: TARGET_SQL
從翻譯輸入查詢中移除 SQL 註解
translation_rules:
- instruction: "Remove all the sql comments in the input sql query."
suggestion_type: QUERY_CUSTOMIZATION
rewrite_target: SOURCE_SQL
使用預設 LLM 提示詞生成翻譯說明
這個範例使用翻譯服務提供的預設 LLM 提示,生成文字說明:
translation_rules:
- suggestion_type: "TRANSLATION_EXPLANATION"
使用您自己的自然語言提示生成翻譯說明
translation_rules:
- suggestion_type: "TRANSLATION_EXPLANATION"
instruction: "Explain the syntax differences between the source Teradata query and the translated GoogleSQL query."
單一 YAML 設定檔中有多種建議類型
translation_rules:
- suggestion_type: "TRANSLATION_EXPLANATION"
instruction: "Explain the syntax differences between the source Teradata query and the translated GoogleSQL query."
- instruction: "Remove upper() function"
suggestion_type: QUERY_CUSTOMIZATION
rewrite_target: TARGET_SQL
examples:
- input: "upper(X)"
output: "X"
- instruction: "Remove all the sql comments in the input sql query."
suggestion_type: QUERY_CUSTOMIZATION
rewrite_target: SOURCE_SQL
套用多個 YAML 設定
在批次或互動式 SQL 翻譯中指定 YAML 設定檔時,您可以在單一翻譯工作中選取多個 YAML 設定檔,以反映多項轉換。如果多項設定發生衝突,其中一項轉換可能會覆寫另一項。建議您在每個檔案中使用不同類型的設定,以免在同一項翻譯工作中發生轉換衝突。
以下範例列出為單一 SQL 轉譯工作提供的兩個獨立設定 YAML 檔案,一個用於變更資料欄屬性,另一個用於將資料表設為暫時:
change-type-example.config.yaml:
type: object_rewriter
attribute:
-
match: "testdb.testschema.x.a"
type:
target: NUMERIC(10,2)
make-temp-example.config.yaml:
type: object_rewriter
relation:
-
match: "testdb.testschema.x"
temporary: true
使用這兩個設定 YAML 檔案的 SQL 翻譯可能如下所示:
teradata-input.sql |
create table x(a int); |
bq-output.sql |
CREATE TEMPORARY TABLE x ( a NUMERIC(31, 2) ) ; |