Presto 驗證器¶
Presto 驗證器是一個執行查詢並驗證正確性的工具。它可以用來測試新的 Presto 版本是否產生正確的查詢結果,或是測試成對的 Presto 查詢是否具有相同的語意。
在每個 Presto 版本發布期間,都會執行驗證器,以確保沒有正確性的回歸。
使用驗證器¶
在 MySQL 資料庫中,建立以下資料表並載入您想要執行的查詢
CREATE TABLE verifier_queries (
id int(11) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
suite varchar(256) NOT NULL,
name varchar(256) DEFAULT NULL,
control_catalog varchar(256) NOT NULL,
control_schema varchar(256) NOT NULL,
control_query text NOT NULL,
control_username varchar(256) DEFAULT NULL,
control_password varchar(256) DEFAULT NULL,
control_session_properties text DEFAULT NULL,
test_catalog varchar(256) NOT NULL,
test_schema varchar(256) NOT NULL,
test_query text NOT NULL,
test_username varchar(256) DEFAULT NULL,
test_password varchar(256) DEFAULT NULL,
test_session_properties text DEFAULT NULL)
接下來,建立一個 config.properties
檔案
source-query.suites=suite
source-query.database=jdbc:mysql://127.0.0.1:3306/mydb?user=my_username&password=my_password
control.hosts=127.0.0.1
control.http-port=8080
control.jdbc-port=8080
control.application-name=verifier-test
test.hosts=127.0.0.1
test.http-port=8081
test.jdbc-port=8081
test.application-name=verifier-test
test-id=1
驗證器可以透過設定組態 running-mode
,在 query-bank
或 control-test
模式下執行。
control-test
:這是預設模式。控制查詢和測試查詢都會被執行,並且它們的結果檢查碼會被比較。query-bank
:在此模式下,控制查詢會被跳過,並且比較會在儲存的快照結果和測試結果之間進行。
建立 verifier_snapshots
資料表
CREATE TABLE verifier_snapshots (
id int(11) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
suite varchar(256) NOT NULL,
name varchar(256) NOT NULL DEFAULT '.',
is_explain BOOLEAN NOT NULL DEFAULT false,
snapshot json NOT NULL,
updated_at datetime NOT NULL DEFAULT now(),
UNIQUE(suite, name, is_explain));
下載 presto-verifier-0.289-executable.jar 並將其重新命名為 verifier.jar
。要執行驗證器
java -Xmx1G -jar verifier.jar verify config.properties
在 query-bank
模式下執行之前,必須儲存快照。新增組態
running-mode=query-bank
save-snapshot=true
執行驗證器,快照將會儲存到資料表 verifier_snapshots
。
若要以 query-bank
模式執行,請設定 save-snapshot=false
或直接刪除它
running-mode=query-bank
#save-snapshot=true
驗證器程序¶
以下步驟總結了驗證器的工作流程。
- 匯入來源查詢
從 MySQL 資料表讀取來源查詢(具有組態的查詢配對)的清單。
- 查詢前處理和篩選
將覆寫套用至每個查詢的目錄、綱要、使用者名稱和密碼。
根據允許清單和封鎖清單篩選查詢。允許清單會在封鎖清單之前套用。
篩選掉具有無效語法的查詢。
篩選掉不支援驗證的查詢。
Select
、Insert
、CreateTableAsSelect
、create table
和create view
都受到支援。
- 查詢重寫
在執行之前重寫查詢,以確保生產資料不會被修改。
- 將
Select
查詢重寫為CreateTableAsSelect
欄位名稱是透過執行帶有
LIMIT 0
的Select
查詢來決定。人工名稱會用於未命名的欄位。
- 將
- 重寫
Insert
和CreateTableAsSelect
查詢,以使其資料表名稱被取代。 建構一個設定查詢,以建立
Insert
查詢所需的資料表。
- 重寫
如果設定組態,則根據
nondeterministic-function-substitutes
重寫函式呼叫。
- 查詢執行
從概念上來說,驗證器會組態有控制叢集和測試叢集。然而,對於某些測試,它們可能會指向相同的 Presto 叢集。在
Query-bank
模式下,控制叢集會被跳過,並改用已儲存的快照。- 對於每個來源查詢,依序執行以下查詢。
控制設定查詢
控制查詢
測試設定查詢
測試查詢
控制和測試拆解查詢
- 查詢會受到逾時和重試的限制。
叢集連線失敗和暫時性 Presto 失敗會被重試。
查詢重試可能會隱藏可靠性問題,因此驗證器會記錄所有發生的 Presto 查詢失敗,包括重試。
某些查詢失敗會自動提交以重新驗證,例如在查詢期間分割區或資料表被捨棄。
請參閱 失敗處理 以取得自動解決查詢失敗的方法。
- 發出結果
驗證結果可以匯出為
JSON
或人類可讀的文字。
欄位檢查碼¶
對於控制/測試查詢中的每個欄位,檢查碼查詢中會產生一個或多個欄位。
- 浮點數欄位
- 對於
DOUBLE
和REAL
欄位,會產生 4 個欄位以進行驗證 欄位中有限值的總和
欄位的
NAN
計數欄位的正無限大計數
欄位的負無限大計數
- 對於
檢查
NAN
計數、正無限大計數和負無限大計數是否符合。檢查控制總和和測試總和的空值性。
如果控制平均值或測試平均值非常接近 0,則檢查兩者是否都接近 0。
檢查控制總和與測試總和之間的相對誤差。
- VARCHAR 欄位
對於
VARCHAR
欄位,會使用checksum()
產生一個簡單的檢查碼欄位以進行驗證。- 如果設定
validate-string-as-double
,則會產生以下七個欄位。如果在將所有值轉換為DOUBLE
之後,NULL
計數相等,則套用浮點數驗證。否則,請檢查簡單的檢查碼是否符合。 檢查碼
NULL
值的計數將所有值轉換為
DOUBLE
後,NULL
值的計數
- 在將所有值轉換為
DOUBLE
之後 有限值的總和
值的
NAN
計數值的正無限大計數
值的負無限大計數
- 如果設定
- 陣列欄位
- 對於類型為
array(E)
的陣列欄位arr
,會產生三個欄位以進行驗證 基數的總和
基數的檢查碼
- 陣列校驗和
如果
E
不可排序,則陣列校驗和為checksum(arr)
。如果
E
可排序,則陣列校驗和為coalesce(checksum(try(array_sort(arr))), checksum(arr))
。
- 對於類型為
- 如果設定了
use-error-margin-for-floating-point-arrays
且 E 為DOUBLE
或REAL
,則會產生以下六個欄位。檢查基數總和是否匹配,以及基數的校驗和是否匹配。將浮點數驗證應用於其餘結果。 基數的總和
基數的檢查碼
所有陣列值的有限元素總和
所有陣列值的
NAN
元素計數所有陣列值的正無限大元素計數
所有陣列值的負無限大元素計數
- 如果設定了
- 如果設定了
validate-string-as-double
且 E 為VARCHAR
,則會產生以下九個欄位。檢查基數的總和與校驗和是否匹配。如果在將所有陣列元素轉換為DOUBLE
之前和之後,NULL
的計數相等,則應用浮點數驗證。否則,檢查陣列校驗和是否匹配。 基數的總和
基數的檢查碼
陣列校驗和
checksum(array_sort(arr))
所有陣列值的
NULL
元素計數將所有陣列元素轉換為
DOUBLE
後的NULL
元素計數
- 將所有陣列元素轉換為
DOUBLE
後 所有陣列值的有限元素總和
所有陣列值的
NAN
元素計數所有陣列值的正無限大元素計數
所有陣列值的負無限大元素計數
- 如果設定了
- 對應欄位
- 對於類型為
map(K, V)
的對應欄位,會產生四個欄位進行驗證 基數的總和
對應的校驗和
鍵集合的陣列校驗和
值集合的陣列校驗和
- 對於類型為
- 如果設定了
validate-string-as-double
且 K 為VARCHAR
,則會產生六個額外欄位 所有鍵集合的
NULL
元素計數將所有對應鍵轉換為
DOUBLE
後,鍵集合的NULL
元素計數
- 將所有對應鍵轉換為
DOUBLE
後 所有鍵集合的有限元素總和
所有鍵集合的
NAN
元素計數所有鍵集合的正無限大元素計數
所有鍵集合的負無限大元素計數
- 如果設定了
- 如果設定了
validate-string-as-double
且 V 為VARCHAR
,則會產生六個額外欄位 所有值集合的
NULL
元素計數將所有對應值轉換為
DOUBLE
後,值集合的NULL
元素計數
- 將所有對應值轉換為
DOUBLE
後 所有值集合的有限元素總和
所有值集合的
NAN
元素計數所有值集合的正無限大元素計數
所有值集合的負無限大元素計數
- 如果設定了
- 列的資料列
根據欄位的類型遞迴計算資料列欄位的校驗和。
對於所有其他欄位類型,使用 checksum()
函數產生一個簡單的校驗和。
決定性¶
結果不匹配(資料列計數不匹配或欄位不匹配)可能是由非決定性的查詢功能引起的。為了避免錯誤警報,我們會對控制查詢執行決定性分析。如果發現查詢不具決定性,我們會跳過驗證,因為它無法提供洞察力。
決定性分析遵循以下步驟。如果在任何時候發現查詢不具決定性,分析將會結束。
可以使用
determinism.non-deterministic-catalog
指定非決定性目錄。如果查詢引用這些目錄中的任何表格,則該查詢會被視為不具決定性。再次執行控制查詢,並將結果與初始控制查詢執行結果進行比較。
- 如果查詢在頂層有
LIMIT n
子句,但沒有ORDER BY
子句 執行查詢以計算控制查詢在沒有
LIMIT
子句的情況下產生的資料列數量。如果產生的資料列計數大於
n
,則將控制查詢視為不具決定性。
- 如果查詢在頂層有
失敗解決¶
組態的差異,包括叢集大小,可能會導致查詢在控制叢集上成功,但在測試叢集上失敗。校驗和查詢也可能會失敗,這可能是由於 Presto 或 Presto Verifier 的限制所致。因此,我們允許 Verifier 自動解決某些查詢失敗。
EXCEEDED_GLOBAL_MEMORY_LIMIT
:如果控制查詢使用的記憶體多於測試查詢,則會解決。EXCEEDED_TIME_LIMIT
:無條件解決。TOO_MANY_HIVE_PARTITIONS
:如果測試叢集沒有足夠的工作節點來確保分配給每個工作節點的分割區數量保持在限制內,則會解決。COMPILER_ERROR
、GENERATED_BYTECODE_TOO_LARGE
:如果控制校驗和查詢因這個錯誤而失敗,則會解決。如果控制查詢的欄位過多,則在某些情況下,產生的校驗和查詢可能會過大。
在結果不匹配的情況下,Verifier 可能會發出雜訊訊號,我們允許 Verifier 自動解決某些不匹配。
- 結構化類型欄位:如果陣列元素或對應鍵/值包含浮點類型,則欄位校驗和不太可能匹配。
對於陣列欄位,如果元素類型包含浮點類型且基數校驗和匹配,則會解決。
- 對於對應欄位,當以下兩個條件都成立時,則會解決不匹配問題
基數校驗和匹配。
不包含浮點類型的鍵或值的校驗和匹配。
僅當所有欄位都解決時,才解決測試案例。
- 已解決的函式:在結果不匹配的情況下,如果查詢在
指定的清單中使用函式,則會將測試案例標記為已解決。
說明模式¶
在說明模式中,Verifier 會檢查是否可以說明來源查詢,而不是檢查它們是否產生相同的結果。當可以說明控制查詢和測試查詢時,會將驗證標記為成功。
輸出事件中的 matchType
欄位可以用來指示控制執行和測試執行之間是否存在計畫差異。
對於非 DML 查詢,會跳過控制查詢和計畫比較。
擴充 Verifier¶
除了組態屬性之外,還可以擴充 Verifier 以進行進一步的行為變更。
AbstractVerifyCommand 顯示了可以擴充的元件。實作抽象類別,並建立類似於 PrestoVerifier 的命令列包裝器。
組態參考¶
一般組態¶
名稱 |
描述 |
---|---|
|
一個以逗號分隔的清單,指定要驗證的套件中的查詢名稱。 |
|
一個以逗號分隔的清單,指定要從套件中排除的查詢名稱。 |
|
來源查詢供應商的名稱。支援 |
|
保存驗證器查詢的表格名稱。僅當 |
|
一個以逗號分隔的清單,指定應在何處發出輸出事件。支援 |
|
|
|
人類可讀事件的輸出檔案。如果未設定,則人類可讀事件會發送到 |
|
要附加到控制目標表格的表格前置詞。 |
|
要附加到測試目標表格的表格前置詞。 |
|
如果為 |
|
如果為 |
|
附加到輸出事件的字串。 |
|
同時驗證的最大數量。 |
|
驗證套件的次數。 |
|
驗證來源查詢的次數。 |
|
浮點數欄位的控制總和與測試總和之間可容忍的最大相對誤差。 |
|
低於此臨界值的浮點數平均值將被視為 |
|
在結果不符的情況下是否執行 teardown 查詢。 |
|
來源查詢重新提交以進行驗證的次數限制。 |
|
設定為 |
|
設定為 |
|
設定為 |
|
函數替換的規格,格式為 用逗號串連函數替換。 選擇一個與原始函數的回傳類型和引數類型相容的函數替換,以產生有效的來源查詢。例如, 如果需要將函數引數應用於函數替換,則將其宣告為識別碼。 |
查詢覆寫配置¶
以下配置控制開始驗證之前查詢元資料修改的行為。測試查詢也有對應的配置,將字首 control
替換為 test
。
名稱 |
描述 |
---|---|
|
如果指定,則將此目錄套用至所有查詢。 |
|
如果指定,則將此綱要套用至所有查詢。 |
|
如果指定,則將此使用者名稱套用至所有查詢。 |
|
如果指定,則將此密碼套用至所有查詢。 |
|
支援 3 個值。 |
|
要套用至所有查詢的會話屬性。 |
查詢執行配置¶
以下配置控制控制叢集上查詢執行的行為。測試叢集也有對應的配置,將字首 control
替換為 test
。
名稱 |
描述 |
---|---|
|
以逗號分隔的控制叢集主機名稱或 IP 位址清單。 |
|
控制叢集的 JDBC 連接埠。 |
|
控制叢集的 HTTP 連接埠。 |
|
代表控制 JDBC 的其他 URL 參數的 |
|
控制查詢和測試查詢的執行時間限制。 |
|
|
|
檢查碼查詢的執行時間限制。 |
|
要在 ClientInfo 中傳遞的 ApplicationName。可用於設定來源。 |
決定性分析器配置¶
名稱 |
描述 |
---|---|
|
是否針對決定性分析中產生的表格執行 teardown 查詢。 |
|
檢查控制查詢決定性的其他控制執行次數上限。 |
|
是否啟用針對具有最上層 |
|
以逗號分隔的非決定性目錄清單。參考這些目錄中的表格的查詢將被視為非決定性。 |
失敗解決配置¶
名稱 |
描述 |
---|---|
|
是否為具有 |
|
是否為具有 |
|
是否啟用由於驗證器限制而導致的失敗的失敗解析器。 |
|
是否為具有 |
|
在控制叢集和測試叢集上設定的每個寫入器的最大儲存桶計數。 |
|
快取測試叢集大小的時間限制。 |
|
是否為結構化類型欄位的欄位不符啟用失敗解析器。 |
|
是否啟用 |
|
以逗號分隔的函數清單。如果查詢使用清單中的任何函數,則會解決不符問題。 |