Lindorm SQL を使用してワイドテーブルデータをクエリしたり、インデックスを作成したりすると、エラーや予期しないクエリパフォーマンスが発生することがあります。このトピックでは、Lindorm SQL の使用に関する一般的な問題とそのソリューションについて説明します。
このトピックで説明する一般的な問題は、LindormTable にのみ適用されます。
セカンダリインデックスの作成が「Executing job number exceed, max job number = 8」というエラーで失敗するのはなぜですか?
LindormTable で列を削除した後、同じ名前の列を再追加すると「column is under deleting」というエラーで失敗するのはなぜですか?
SQL クエリが「The estimated memory used by the query exceeds the maximum limit」というエラーで失敗するのはなぜですか?
一括更新がサポートされていない、または「Update's WHERE clause can only contain PK columns」というエラーが発生するのはなぜですか?
非効率なクエリを解決または回避する方法
非効率なクエリとは何か、その特徴は?
クエリ文に、既存のプライマリキーまたはインデックスを効果的に使用できないフィルター条件が含まれている場合、クエリは 全表スキャン を実行する必要があります。このタイプのクエリは非効率と見なされます。
クエリを実行したときに LindormTable がエラー This query may be a full table scan and thus may have unpredictable performance を返した場合、そのクエリは非効率です。たとえば、`test` テーブルの複合プライマリキーが `p1`、`p2`、`p3` の 3 つの列で構成されているとします。`p1` 列はプライマリキーの最初の列です。クエリ SELECT * FROM test WHERE p2=10; を考えてみましょう。この場合、クエリ条件には最初のプライマリキー列 `p1` が含まれていません。したがって、このクエリ文は非効率と見なされます。
デフォルトでは、Lindorm は非効率なクエリを検出してブロックします。これらのクエリはデータベースのパフォーマンスと安定性を低下させる可能性があるためです。
WHERE 句にプライマリキー列またはインデックスキー列が含まれているにもかかわらず、クエリが非効率なクエリ例外をトリガーするのはなぜですか?
LindormTable のプライマリキーとセカンダリインデックスのマッチング規則は、MySQL の複合インデックスの規則に似ています。どちらも最左プレフィックスルールに従います。これは、複数の列を持つ複合プライマリキーまたはインデックスの場合、システムがクエリ条件の列を、最初の (最も左の) 列から順にキー列と照合することを意味します。クエリ条件にプライマリキーまたはインデックスキーの最初の列が含まれていない場合、クエリはプライマリキーまたはセカンダリインデックスにヒットしません。これにより、非効率なクエリが発生します。
たとえば、`test` テーブルのプライマリキーが `p1`、`p2`、`p3` の 3 つの列で構成されているとします。`p1` 列はプライマリキーの最初の列です。最左プレフィックスルールに従って、システムはデータをクエリする際に `p1` 列からマッチングを開始します。クエリ条件に SELECT * FROM test WHERE p2<30; のように `p1` 列が含まれていない場合、システムは最初のプライマリキー列 `p1` を照合できません。クエリはプライマリキーにヒットせず、システムは代わりにテーブル全体をスキャンしてクエリ条件 p2<30 を満たします。
非効率なクエリを回避する方法
アプリケーションで非効率なクエリを回避するには、次の方法を使用できます。
クエリ条件を最適化します。テーブルのプライマリキーを WHERE 句に追加するか、クエリ条件の列が最左プレフィックスルールに従っていることを確認します。
大きなクエリを回避するために、テーブルのプライマリキーの設計を変更します。詳細については、「ワイドテーブルのプライマリキーを設計する方法」をご参照ください。
テーブルのセカンダリインデックスを作成します。詳細については、「セカンダリインデックス」をご参照ください。
テーブルの複数の列で多次元検索を実行するには、テーブルの検索インデックスを作成してクエリを高速化します。詳細については、「検索インデックス」をご参照ください。
クエリ文に
/*+ _l_allow_filtering_ */HINT を追加して、LindormTable に非効率なクエリを強制的に実行させます。例:SELECT /*+ _l_allow_filtering_ */ * FROM dt WHERE nonPK=100;。重要非効率なクエリを強制的に実行すると、パフォーマンスと安定性にリスクが生じる可能性があります。この方法は注意して使用してください。
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 操作によって作成されるグループの数が多すぎます。この操作は過剰なメモリリソースを消費し、インスタンスの負荷を増加させる可能性があります。そのため、LindormTable は結果セットに多数のグループを生成するクエリを制限します。
ソリューション:
クエリ文にフィルター条件を追加して、最終的なグループ数を減らします。
Lindorm テクニカルサポート (DingTalk ID: s0s3eg3) に連絡して、グループ数のしきい値を増やしてください。
重要グループ数のしきい値を増やすと、インスタンスの安定性に影響する可能性があります。
多次元クエリシナリオでは、検索インデックスの使用を推奨します。詳細については、「検索インデックスの概要」をご参照ください。
動的カラムが有効なテーブルに対する「SELECT *」クエリが「Limit of this select statement is not set or exceeds config when select all columns from table with property DYNAMIC_COLUMNS=true」というエラーで失敗するのはなぜですか?
原因:
動的カラムが有効なテーブルには、多数の動的カラムが含まれている可能性があり、そのスキーマは固定されていません。このようなテーブルで全表スキャンを実行すると、高い I/O 消費を引き起こし、インスタンスの負荷を増加させる可能性があります。高負荷の状況を防ぐために、LindormTable は動的カラムを持つテーブルのクエリ文に制限を設けています。
ソリューション:
SELECT 文に LIMIT 句を追加して、返される結果の数を制限します。例: SELECT * FROM test LIMIT 10;。
セカンダリインデックスの作成が「Executing job number exceed, max job number = 8」というエラーで失敗するのはなぜですか?
原因:
インスタンスでは、最大 8 つのセカンダリインデックス構築タスクを同時に実行できます。すでに 8 つの構築タスクが実行中の場合、セカンダリインデックスを新たに作成しようとすると、このエラーで失敗します。
ソリューション:
多数のセカンダリインデックスを同時に作成することは避けてください。多数のインデックスを作成するには、Lindorm テクニカルサポート (DingTalk ID: s0s3eg3) に連絡してください。
LindormTable で列を削除した後、同じ名前の列を再追加すると「column is under deleting」というエラーで失敗するのはなぜですか?
原因:
データの型などの要因によるダーティデータの問題を防ぐため、LindormTable は列を削除した後、メモリ、ホットストレージ、コールドストレージから列のデータを非同期でクリーンアップします。クリーンアッププロセスが完了するまで、システムは同じ名前の新しい列の追加を許可しません。
ソリューション:
データのクリーンアップはシステムによって実行され、時間がかかる場合があります。次の方法を使用して、クリーンアッププロセスを高速化できます。クリーンアップが完了したら、同じ名前の列を再度追加できます。
列が削除されたテーブルの名前が 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 */ HINT を使用する場合)、プライマリテーブルとセカンダリインデックステーブルの両方の可変性は MULTABLE_ALL である必要があります。ただし、パフォーマンス上の理由から、Lindorm はプライマリテーブルとインデックステーブルの可変性をデフォルトで MULTABLE_LATEST に設定します。この構成でセカンダリインデックスを作成して有効にすると、可変性の制約違反がトリガーされ、エラーが発生します。
ソリューション:
MUTABILITY パラメーターの値は、インデックステーブルが作成された後は変更できません。まず、元のセカンダリインデックスを削除する必要があります。
プライマリテーブルから元のセカンダリインデックスを削除します。
-- 元のセカンダリインデックスを無効にします。 ALTER INDEX IF EXISTS <original_secondary_index_name> ON <primary_table_name> DISABLED; -- 元のセカンダリインデックスを削除します。 DROP INDEX IF EXISTS <original_secondary_index_name> ON <primary_table_name>;DROP INDEX構文の詳細については、「セカンダリインデックスの削除」をご参照ください。プライマリテーブルの MUTABILITY プロパティの値を
MUTABLE_ALLに変更します。ALTER TABLE IF EXISTS <primary_table_name> SET MUTABILITY='MUTABLE_ALL';新しいセカンダリインデックスを作成してデータを書き込みます。セカンダリインデックスを作成するための構文の詳細については、「CREATE INDEX」をご参照ください。
説明カスタムタイムスタンプを使用してデータを書き込む方法の詳細については、「HINT を使用して多バージョンデータ管理のタイムスタンプを設定する」をご参照ください。
セカンダリインデックスの可変性制約とカスタムタイムスタンプの関係の詳細については、「カスタムタイムスタンプでインデックスを更新する」をご参照ください。
SQL クエリが「Code grows beyond 64 KB」というエラーで失敗するのはなぜですか?
原因:
Lindorm SQL エンジンは、Just-In-Time (JIT) コンパイルを使用してクエリを実行します。クエリの物理プランからバイトコードを動的に生成し、それをコンパイルして実行します。Code grows beyond 64KB エラーは、生成されたメソッドのバイトコードのサイズが Java 仮想マシン (JVM) で許容される制限を超えたことを示します。これは、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 ID: s0s3eg3) に連絡して、メモリ制限のしきい値を増やしてください。重要オンラインアプリケーションのクエリ同時実行性が高い場合、このメモリ制限のしきい値を増やすと、Lindorm のメモリ負荷が増加する可能性があります。これにより、強制的な Full GC などの動作がトリガーされ、クラスター全体の応答性が低下する可能性があります。したがって、このメモリ制限を増やす前に、十分な評価を行ってください。SHOW VARIABLES 文を使用して、
QUERY_MAX_MEMの現在の値を取得できます。
一括更新がサポートされていない、または「Update's WHERE clause can only contain PK columns」というエラーが発生するのはなぜですか?
デフォルトでは、単一行の更新のみがサポートされています。この機能を有効にする方法の詳細については、「一括操作に関するよくある質問」をご参照ください。
一括削除を有効にする方法
一括削除を有効にし、設定を確認する方法の詳細については、「一括操作に関するよくある質問」をご参照ください。