在使用Lindorm SQL查詢寬表資料或建立索引時,可能會遇到報錯或出現查詢效能不符合預期的情況。本文介紹Lindorm SQL使用時的常見問題和解決方案。
本文列舉的常見問題僅適用於寬表引擎。
如何解決或規避低效查詢問題?
什麼是低效查詢?低效查詢有哪些特點?
如果查詢語句中帶有過濾條件,但該過濾條件無法有效地利用已有的主鍵或索引,導致查詢時必須掃描全表,這樣的查詢被視為低效查詢。
如果執行查詢語句後,寬表引擎報錯This query may be a full table scan and thus may have unpredictable performance,表示該查詢是低效查詢。假設test表的聯合主鍵由p1,p2,p3三個列組成,p1列是主鍵的第一列,查詢條件為SELECT * FROM test WHERE p2=10;。此時查詢條件中未包含第一個主鍵列p1,因此該查詢語句會被認定為低效查詢語句。
由於低效查詢可能會帶來效能穩定性風險,預設情況下Lindorm會檢測並阻止低效查詢的執行。
查詢條件WHERE中的列是主鍵列或索引列,為什麼查詢還是觸發了低效查詢異常?
寬表引擎的主鍵、二級索引和MySQL聯合索引的匹配規則類似,均遵循最左匹配原則,即在多個列組成的聯合主鍵或索引中,系統從主鍵或索引鍵的第一列(最左側列)開始逐一與查詢條件中的列進行匹配。如果查詢條件中不包含主鍵或索引鍵的第一列,則此時查詢仍不會命中主鍵或二級索引,導致查詢仍然是低效查詢。
假設test表的主鍵由p1、p2、p3三個列組成,p1列是主鍵的第一列,根據最左匹配原則,查詢資料時系統將從p1列開始匹配。如果查詢條件中未包含p1列,例如SELECT * FROM test WHERE p2<30;,此時無法匹配到主鍵第一列p1,系統不會命中主鍵進而查詢全表資料以滿足查詢條件p2<30。
如何規避低效查詢?
以下是業務中規避低效查詢的一些推薦的方法:
使用GROUP BY查詢時報錯The diff group keys of subPlan is over lindorm.aggregate.subplan.groupby.keys.limit=..., it may cost a lot memory so we shutdown this SubPlan?
原因:
GROUP BY操作形成的分組數過多,可能消耗了大量的記憶體資源,從而加重執行個體負載,因此寬表引擎節流了結果集中分組數過大的查詢。
解決方案:
在查詢語句中添加過濾條件,減少最終分組數。
聯絡Lindorm支援人員(DingTalk號:s0s3eg3)調大分組數的閾值。
重要調大分組數的閾值可能會影響執行個體的穩定性。
針對多維查詢匹配情境,建議使用搜尋索引。詳細介紹,請參見搜尋索引介紹。
對開啟動態列的表執行SELECT *查詢報錯Limit of this select statement is not set or exceeds config when select all columns from table with property DYNAMIC_COLUMNS=true?
原因:
開啟動態列的表可能包含大量的動態列,且表的Schema定義不固定。如果對這類表進行全表掃描,將會導致IO消耗嚴重,加重執行個體負載。為避免高負載情況的產生,Lindorm寬表引擎對動態列表的查詢語句進行了限制。
解決方案:
在SELECT語句中添加LIMIT子句,限制返回結果的數量。例如SELECT * FROM test LIMIT 10;。
為什麼建立二級索引時報錯Executing job number exceed, max job number = 8?
原因:
一個執行個體中僅允許同時存在8個二級索引的構建任務。如果某一時刻二級索引的構建任務數已達8個,則再次建立新的二級索引時,建立語句將會報錯。
解決方案:
建議您避免同時建立大量二級索引。如果有大量建立的需求,請聯絡Lindorm支援人員(DingTalk號:s0s3eg3)。
在寬表引擎上已執行刪除列操作,為什麼重新添加同名列時會報錯column is under deleting?
原因:
為避免由於資料類型等因素引發的髒資料問題,在您執行刪除列的操作後,寬表引擎還需要非同步清理記憶體、熱儲存和冷儲存上該列的資料。在資料全部清理完之前,系統不允許重新添加同名的新列。
解決方案:
由於資料清理由系統自行完成,可能會消耗很長時間。建議您通過以下方式加速資料的清理過程,待資料清理完成之後重新添加同名列。
假設執行了刪除列操作的表名為dt:
-- 執行FLUSH操作,強制將記憶體中殘留的資料刷到儲存媒介上
ALTER TABLE dt FLUSH;
-- 執行COMPACTION操作,執行資料的合并和刪除
ALTER TABLE dt COMPACT;FLUSH文法從SQL引擎2.7.1版本開始支援。如何查看SQL引擎的版本,請參見SQL版本說明。FLUSH操作和COMPACT操作是非同步作業。語句執行成功並不代表資料清理完成,需要等待一段時間才能徹底清理完成。對資料量大的表執行
COMPACT操作,其執行期間會佔用較多系統資源,因此不建議在業務高峰期執行。
建立二級索引後,寫入資料時為什麼會報錯Performing put operations with User-Defined-Timestamp in indexed column on MULTABLE_LATEST table is unsupported?
原因:
如果寫入時顯式指定了自訂時間戳記(例如,使用UPSERT語句寫入資料時,通過/*+ _l_ts */指定了自訂時間戳記),此時要求主表與二級索引表之間的可變性(Mutability)必須是MULTABLE_ALL。但是出於效能考慮,Lindorm系統預設將主表與索引表的可變性配置為MULTABLE_LATEST,在這種配置下建立二級索引並啟用會觸發可變性約束限制,導致報錯。
解決方案:
由於建立索引表後MUTABILITY參數的值不支援修改,因此您需要先刪除原有的二級索引。
刪除主表中原有的二級索引。
-- 禁用原有二級索引 ALTER INDEX IF EXISTS <原有二級索引名> ON <主表名> DISABLED; -- 刪除原有二級索引 DROP INDEX IF EXISTS <原有二級索引名> ON <主表名>;DROP INDEX文法的詳細介紹,請參見刪除二級索引。將主表的MUTABILITY屬性的值修改為
MUTABLE_ALL。ALTER TABLE IF EXISTS <主表名> SET MUTABILITY='MUTABLE_ALL';建立新的二級索引,並寫入資料。建立二級索引的文法說明,請參見CREATE INDEX。
說明自訂時間戳記的寫入方式,請參見通過HINT設定時間戳記實現多版本資料管理。
二級索引可變性約束與自訂時間戳記的關係,請參見更新自訂時間戳記的索引。
執行SQL查詢時,為什麼會報錯Code grows beyond 64 KB?
原因:
Lindorm的SQL引擎在執行查詢時採用了JIT編譯技術,會將查詢的物理計划動態產生位元組碼並編譯執行。Code grows beyond 64KB報錯是指產生的方法函數的位元組碼大小超過了Java虛擬機器允許的上限,這可能是因為指定的SQL查詢語句中的個別謂詞過於冗長或複雜,導致產生的位元組碼過大無法被執行。
解決方案:
修改指定的SQL語句,簡化相關的謂詞表達。
執行SQL查詢時,為什麼會報錯The estimated memory used by the query exceeds the maximum limit?
原因:
SQL引擎在處理儲存引擎返回的結果集時(例如彙總、排序、去重)通常需要消耗大量記憶體資源。由於Lindorm SQL主要面向線上業務情境,同一時刻可能存在大量查詢並發執行,為保證高並發情境下的查詢效率,系統對單個查詢的記憶體使用量進行了限制。當前預設限制為8 MB,超出時會觸發記憶體溢出異常。
解決方案:
最佳化查詢語句。可以結合索引的使用等嘗試將運算元下推到儲存引擎中執行,或通過最佳化過濾條件,減少SQL引擎計算的資料量。
說明您可以通過解讀執行計畫來查看彙總、排序等運算元是否下推到儲存引擎執行,或由SQL引擎執行。
調整記憶體限制閾值QUERY_MAX_MEM。您可以在充分評估了查詢吞吐的情況下,通過 ALTER SYSTEM 語句調整QUERY_MAX_MEM配置項進行調整,例如
ALTER SYSTEM SET QUERY_MAX_MEM = 8388608;。如果您使用的SQL引擎版本低於 2.9.6.0,可聯絡Lindorm支援人員(DingTalk號:s0s3eg3)調大記憶體限制閾值。重要當線上應用的查詢並發度較高時,直接調大該記憶體限制的閾值可能會加重 Lindorm 的記憶體使用量負載,進而引發強制的 Full GC 等行為,從而降低整個叢集的響應能力。因此,調大該記憶體限制前請務必充分評估。
QUERY_MAX_MEM當前的生效值可通過 SHOW VARIABLES 語句查詢。