このトピックでは、PolarDB for MySQL のインメモリ列インデックス (IMCI) 機能に関するよくある質問 (FAQ) を紹介します。
PolarDB for MySQL の IMCI 機能の使用方法
IMCI 機能を使用してクエリを高速化するには、次の手順を実行します。
IMCI 機能が有効な読み取り専用ノードを PolarDB for MySQL クラスターに追加します。詳細については、「IMCI 機能が有効な読み取り専用ノードの追加」をご参照ください。
アクセスを高速化したいテーブルに列ストアインデックスを追加します。これを行うには、
CREATE TABLE文またはALTER TABLE文を使用して、テーブルのCOMMENTフィールドにCOLUMNAR=1属性を追加します。列ストアインデックスの準備が完了すると、オプティマイザーは実行コストに基づいて、クエリに列ストアインデックスを使用するかどうかを自動的に判断します。構文の詳細については、「テーブル作成時の列ストアインデックス作成のための DDL 構文」をご参照ください。SQL 文を列ストアノードに転送する必要があります。実行コストが特定のしきい値を超えると、オプティマイザーは自動的にクエリに列ストアインデックスを使用します。リクエストの自動および手動配信の詳細については、「行ストアノードと列ストアノード間の自動リクエスト配信の設定」をご参照ください。
列ストアインデックスのステータスの確認方法
ALTER TABLE 文を使用して既存のテーブルに列ストアインデックスを動的に追加すると、インデックスは列ストアの読み取り専用ノードで非同期に構築されます。リクエストの自動配信が有効になっているクラスターエンドポイントに接続するか、列ストアノードに直接接続できます。その後、INFORMATION_SCHEMA.IMCI_INDEXES テーブルをクエリして、列ストアインデックスの構築ステータスを取得できます。クエリに使用できるのは、COMMITTED 状態の列ストアインデックスのみです。構築中の列ストアインデックスについては、INFORMATION_SCHEMA.IMCI_ASYNC_DDL_STATS テーブルをクエリして、インデックス構築の進捗に関する情報を取得できます。詳細については、「インデックスステータスの表示」をご参照ください。
Data Management (DMS) を使用してデータベースにログインすると、デフォルトでクラスターのプライマリエンドポイントに接続されます。別のクラスターエンドポイントに接続するか、列ストアノードに直接接続するには、次の手順に従ってください。
クラスターエンドポイントへの接続
DMS 5.0 にログインします。[インスタンスの追加] ページで、[エントリメソッド] を 接続文字列 に設定し、クラスターエンドポイントを入力します。詳細については、「ApsaraDB インスタンスの追加」をご参照ください。
列ストアノードへの直接接続
まず、ターゲットの列ストアノード用にカスタムクラスターエンドポイントを作成します。このカスタムエンドポイントには、ターゲットの列ストアノードのみを含める必要があります。次に、DMS 5.0 にログインします。[インスタンスの追加] ページで、[エントリメソッド] を 接続文字列 に設定し、列ストア読み取り専用ノードのカスタムクラスターエンドポイントを入力します。詳細については、「ApsaraDB インスタンスの追加」をご参照ください。
SQL 文が列ストアインデックスを使用していることの確認と実行計画の表示方法
EXPLAIN 文を使用して、SQL 文の実行計画を表示できます。実行計画に IMCI Execution Plan が含まれている場合、その SQL 文は列ストアインデックスを使用してクエリを高速化しています。以下に実行計画のサンプルを示します。
*************************** 1. row ***************************
IMCI Execution Plan (max_dop = 8, max_query_mem = 3435134976):
Project | Exprs: temp_table3.lineitem.L_ORDERKEY, temp_table3.SUM(lineitem.L_EXTENDEDPRICE * 1.00 - lineitem.L_DISCOUNT), temp_table3.orders.O_ORDERDATE, temp_table3.orders.O_SHIPPRIORITY
Sort | Exprs: temp_table3.SUM(lineitem.L_EXTENDEDPRICE * 1.00 - lineitem.L_DISCOUNT) DESC,temp_table3.orders.O_ORDERDATE ASC
HashGroupby | OutputTable(3): temp_table3 | Grouping: lineitem.L_ORDERKEY orders.O_ORDERDATE orders.O_SHIPPRIORITY | Output Grouping: lineitem.L_ORDERKEY, orders.O_ORDERDATE, orders.O_SHIPPRIORITY | Aggrs: SUM(lineitem.L_EXTENDEDPRICE * 1.00 - lineitem.L_DISCOUNT)
HashJoin | HashMode: DYNAMIC | JoinMode: INNER | JoinPred: orders.O_ORDERKEY = lineitem.L_ORDERKEY
HashJoin | HashMode: DYNAMIC | JoinMode: INNER | JoinPred: orders.O_CUSTKEY = customer.C_CUSTKEY
CTableScan | InputTable(0): orders | Pred: (orders.O_ORDERDATE < 03/24/1995 00:00:00.000000)
CTableScan | InputTable(1): customer | Pred: (customer.C_MKTSEGMENT = "BUILDING")
CTableScan | InputTable(2): lineitem | Pred: (lineitem.L_SHIPDATE > 03/24/1995 00:00:00.000000)
1 row in set (0.04 sec)列ストアインデックスを使用する SQL 文の実行計画は、ツリー状の構造をしています。各レイヤーはオペレーターを表します。オペレーターは通常、SQL 文内の操作と 1 対 1 で対応します。たとえば、CTableScan オペレーターはテーブルのスキャンを示し、HashJoin オペレーターは SQL 文の JOIN 部分に対応し、HashGroupby オペレーターは GROUP BY 部分に対応します。ただし、Sequence などの一部のオペレーターは、クエリの最適化中に生成され、元の SQL のどの文にも対応しません。
SQL 実行計画で列インデックスが使用されない理由のトラブルシューティング・クエリで列のストアが使用されない理由・列ストアノードを追加しても SQL 実行計画が変更されない理由・列インデックスが特定の SQL 文をサポートしているかどうかの判断方法・「自動行/列ストアクエリルーティング」機能が機能しない理由
列ストアノードを追加した後、SQL 文でクエリされるテーブルに列ストアインデックスを追加する必要があります。SQL 文の実行コストが特定のしきい値を超えた場合にのみ、クエリに列ストアインデックスが使用されます。さらに、クエリの高速化に IMCI 機能を使用するには、SQL 文を列ストアノードに転送する必要があります。SQL 文がクエリに列ストアインデックスを使用できない場合は、次の手順で問題をトラブルシューティングできます。
SQL 文が列ストアノードに転送されていることを確認する。
SQL Explorer 機能を使用して、SQL 文が列ストアノードに転送されているかどうかを確認できます。
クラスターエンドポイントを使用し、リクエストの自動配信機能を有効にしている場合、データベースプロキシは、推定クエリコストが
imci_ap_thresholdの値を超える SQL 文を自動的に列ストアノードに転送します。また、SQL 文の SELECT キーワードの前に/*FORCE_IMCI_NODES*/ヒントを追加して、文を強制的に列ストアノードに転送することもできます。例:/*FORCE_IMCI_NODES*/EXPLAIN SELECT COUNT(*) FROM t1 WHERE t1.a > 1;詳細については、「行ストアノードと列ストアノード間の自動リクエスト配信の設定」をご参照ください。
説明新しいエンドポイントを作成して列ストアノードに直接接続することもできます。これにより、SQL 文は常に列ストアノードに転送されて実行されるようになります。
クエリの実行コストが指定されたしきい値より高いかどうかを確認する。
列ストアノードでは、オプティマイザーが SQL 文のコストを推定します。推定コストが指定されたしきい値
cost_threshold_for_imciよりも高い場合、クエリに列ストアインデックスが使用されます。それ以外の場合は、既存の行ストアインデックスが使用されます。SQL 文が列ストアノードに転送されていることを確認した後、EXPLAIN を実行しても実行計画が列ストアインデックスを使用しない場合は、推定コストが低すぎるかどうかを確認します。
Last_query_cost変数をクエリして、前の SQL 文の推定実行コストを取得できます。EXPLAIN SELECT * FROM t1; SHOW STATUS LIKE 'Last_query_cost';推定実行コストが事前に設定された
cost_threshold_for_imciの値よりも低い場合は、cost_threshold_for_imciの値を調整することを検討できます。たとえば、ヒントを使用して単一の SQL 文のしきい値を調整できます。/*FORCE_IMCI_NODES*/EXPLAIN SELECT /*+ SET_VAR(cost_threshold_for_imci=0) */ COUNT(*) FROM t1 WHERE t1.a > 1;SQL 文で必要なすべての列が列ストアインデックスでカバーされているかを確認する。
組み込みのストアドプロシージャ
dbms_imci.check_columnar_index()を使用して、SQL 文内のテーブルに対して列ストアインデックスが作成されているかどうかを確認できます。例:CALL dbms_imci.check_columnar_index('SELECT COUNT(*) FROM t1 WHERE t1.a > 1');SQL 文が列ストアインデックスで完全にカバーされていない場合、このストアドプロシージャを呼び出すと、カバーされていないテーブルと列が返されます。完全にカバーされている場合は、空の結果セットが返されます。
サポートされていない SQL 機能を確認します。
制限事項のリストを参照して、特定の SQL 機能が列ストアインデックスをサポートしているかどうかを確認できます。
上記のすべてのチェックに合格した場合、SQL 文はクエリに列ストアインデックスを使用するはずです。
列ストアノードは行ストアインデックスを使用できるか
列ストア読み取り専用ノードは、IMCI 機能を備えた通常の読み取り専用ノードです。したがって、列ストアノードは行ストアインデックスと列ストアインデックスの両方を使用できます。オプティマイザーは cost_threshold_for_imci のしきい値に基づいてインデックスを選択します。
ヒントを使用して単一の SQL 文のクエリしきい値を設定し、列ストアインデックスを強制的に使用させることができます。
SELECT /*+ SET_VAR(cost_threshold_for_imci=0) */ COUNT(*) FROM t1 WHERE t1.a > 1;SQL 文が列ストアインデックスを使用しないように強制することもできます。
SELECT /*+ SET_VAR(USE_IMCI_ENGINE=OFF) */ COUNT(*) FROM t1 WHERE t1.a > 1;SQL 文に適した列ストアインデックスの追加方法
SQL 文がクエリに列ストアインデックスを使用するには、文で使用されるすべての列が列ストアインデックスでカバーされている必要があります。SQL 文に関係する列がカバーされていない場合は、CREATE TABLE 文または ALTER TABLE 文を使用して列ストアインデックスに追加できます。PolarDB for MySQL は、この操作を支援するための一連の組み込みストアドプロシージャを提供します。
dbms_imci.columnar_advise() ストアドプロシージャを使用して、SQL 文に必要な DDL 文を取得できます。この DDL 文に従って列ストアインデックスを構築すると、SQL 文は列ストアインデックスによって完全にカバーされます。詳細については、「列ストアインデックスを作成するための DDL 文の取得」をご参照ください。
dbms_imci.columnar_advise('<query_string>');Multi-master Cluster (Limitless) Edition を使用している場合、このストアドプロシージャはグローバル読み取り専用ノードで実行する必要があります。SQL 文の前に /*force_node='<Node ID>'*/ を追加して、グローバル読み取り専用ノードでの実行を強制できます。例: /*force_node='pi-bpxxxxxxxx'*/ dbms_imci.columnar_advise('<query_string>')。
dbms_imci.columnar_advise_begin()、dbms_imci.columnar_advise_end()、および dbms_imci.columnar_advise() インターフェイスを使用して、SQL 文のバッチに必要な DDL 文を取得できます。詳細については、「バッチでの列ストアインデックス作成のための DDL 文の取得」をご参照ください。
PolarDB for MySQL IMCI:単一ノードのパラレルクエリのサポートと並列度のカスタマイズ方法
単一ノードのパラレルクエリはデフォルトで有効になっています。EXPLAIN を使用して実行計画を表示できます。max_dop フィールドは、実際に使用された並列度を示します。特定の SQL 文の並列度をカスタマイズするには、SQL 文を実行する前にセッションレベルで imci_max_dop パラメーターを設定します。例:
set imci_max_dop=8; explain select xxxx列ストアノードの CPU またはメモリ使用率が高い場合の対処法とモニタリング設定
デフォルトでは、単一の SQL 文は同時に実行され、利用可能なすべての CPU リソースを使用できます。複数の SQL 文が同時に実行されると、データベース内の内部スケジューラが SQL 文をスケジュールし、各文の CPU およびメモリ制限を動的に削減します。そのため、列ストアノードは他のノードと比較して平均 CPU およびメモリ使用率が高くなる傾向があります。
imci_max_dopパラメーターを調整して、単一の SQL 文の最大並列度を制御し、単一の SQL 文が使用できる CPU コアの数を制限できます。CPU のモニタリングしきい値は CPU 使用率の 70% に、メモリのモニタリングしきい値はメモリ使用量の 90% に設定することを推奨します。
PolarDB for MySQL では、同じクラスター内に異なる仕様のノードを持つことができます。列ストアノードの仕様を個別にスペックアップまたはスペックダウンできます。列ストアノードには、少なくとも 8 コアと 16 GB のメモリを搭載することを推奨します。
PolarDB for MySQL 5.6 および 5.7 での IMCI 機能のサポート
PolarDB for MySQL 5.6 および 5.7 は IMCI 機能をサポートしていません。PolarDB for MySQL 8.0 は IMCI 機能をサポートしています。
IMCI 機能の制限事項、MySQL との互換性、フルテキストインデックスのサポート
IMCI 機能は MySQL と完全に互換性があります。ただし、特定の時空間式、フルテキストインデックス、一部の形式の相関サブクエリなど、あまり一般的でない一部のクエリ機能はまだ完全にはサポートされていません。これらの機能を使用する SQL 文は列ストアインデックスを使用できず、クエリに行ストアインデックスを使用するようにフォールバックします。IMCI 機能の制限事項の詳細については、「制限事項」をご参照ください。
INSERT INTO SELECT 文および CREATE TABLE AS SELECT 文での列ストアインデックスの使用
INSERT 文および CREATE 文はプライマリ (RW) ノードでのみ実行できますが、IMCI クエリは読み取り専用ノードで実行されます。したがって、INSERT INTO SELECT 文または CREATE TABLE AS SELECT 文で列ストアインデックスを使用するには、IMCI ETL 機能を使用する必要があります。詳細については、「列ストアインデックスを使用した ETL の高速化」をご参照ください。
IMCI 機能の料金とホットスタンバイが無効な読み取り専用ノードでの使用
IMCI 機能自体は別途課金されません。ただし、IMCI 機能を使用するには、IMCI が有効な専用の読み取り専用ノードを追加する必要があります。この新しい読み取り専用ノードと、テーブル上の列ストアインデックスが消費する追加のストレージに対して課金されます。
ホットスタンバイが無効な読み取り専用ノードは、IMCI 機能をサポートしていません。
列ストアインデックスが使用する追加のストレージ容量
列ストアインデックスはデータを列ごとに整理するため、行ストアよりも 3〜10 倍高い圧縮率を提供しますが、その代償として容量使用量が 10%〜30% 増加します。
列ストアインデックスが使用するストレージ容量の表示方法
PolarDB for MySQL 8.0.1.1.32 以前のクラスターバージョンの場合、
information_schemaのimci_columnsシステムテーブルをクエリして、列ストアインデックスを持つテーブルのストレージ容量と列の圧縮率を表示できます。たとえば、testデータベースのtestテーブルのストレージ容量と圧縮率を表示するには、次の SQL 文を実行します。SELECT SCHEMA_NAME, TABLE_NAME, SUM(EXTENT_SIZE * TOTAL_EXTENT_COUNT) AS TOTAL_SIZE, SUM(EXTENT_SIZE * USED_EXTENT_COUNT) AS USED_SIZE, SUM(EXTENT_SIZE * FREE_EXTENT_COUNT) AS FREE_SIZE, SUM(RAW_DATA_SIZE) / SUM(FILE_SIZE) AS COMPRESS FROM information_schema.imci_columns WHERE SCHEMA_NAME = 'test' AND TABLE_NAME = 'test';PolarDB for MySQL 8.0.1.1.33 以降のクラスターバージョンの場合、
information_schemaのimci_data_filesシステムテーブルをクエリしてストレージ容量を表示し、imci_columnsシステムテーブルをクエリして列の圧縮率を表示できます。たとえば、testデータベースのtestテーブルのストレージ容量と列の圧縮率を表示するには、次の SQL 文を実行します。列ストアインデックスを持つ
testテーブルが使用するストレージ容量を表示します。次の SQL 文を実行します。SELECT SCHEMA_NAME, TABLE_NAME, SUM(EXTENT_SIZE * TOTAL_EXTENT_COUNT) AS TOTAL_SIZE, SUM(EXTENT_SIZE * USED_EXTENT_COUNT) AS USED_SIZE, SUM(EXTENT_SIZE * FREE_EXTENT_COUNT) AS FREE_SIZE FROM INFORMATION_SCHEMA.IMCI_DATA_FILES WHERE SCHEMA_NAME = 'test' AND TABLE_NAME = 'test';列の圧縮率を表示します。次の SQL 文を実行します。
SELECT SCHEMA_NAME, TABLE_NAME, SUM(RAW_DATA_SIZE) / SUM(CMP_DATA_SIZE) AS COMPRESS_RATIO FROM INFORMATION_SCHEMA.IMCI_COLUMNS WHERE SCHEMA_NAME = 'test' AND TABLE_NAME = 'test';
次の表に、上記の SQL 文のパラメーターを説明します。
パラメーター | 説明 |
SCHEMA_NAME | データベース名。 |
TABLE_NAME | テーブル名。 |
EXTENT_SIZE | エクステントのサイズ。単位:バイト。 |
TOTAL_EXTENT_COUNT | エクステントの総数。 |
USED_EXTENT_COUNT | 使用済みエクステントの数。 |
FREE_EXTENT_COUNT | 空きエクステントの数。 |
RAW_DATA_SIZE | 圧縮前の列データのサイズ。単位:バイト。 |
FILE_SIZE | 圧縮後の列データのサイズ。単位:バイト。 説明 このパラメーターは、8.0.1.1.33 より前のバージョンの PolarDB for MySQL に適用されます。 |
CMP_DATA_SIZE | 圧縮後の列データのサイズ。単位:バイト。 説明 このパラメーターは、PolarDB for MySQL 8.0.1.1.33 以降に適用されます。 |
列ストアインデックス追加後にインスタント DDL が有効にならない理由
PolarDB for MySQL 8.0.1.1.42 および 8.0.2.2.23 より前のバージョンでは、テーブルレベルの IMCI を持つテーブルに列を追加する操作には、インスタント列追加ロジックは適用されません。これは、これらの操作が IMCI 構造の変更を伴い、インデックスデータの再構築が必要になるためです。
PolarDB for MySQL 8.0.1.1.42 以降、および 8.0.2.2.23 以降では、テーブルレベルの IMCI を持つテーブルでインスタント DDL がサポートされています。この機能は、以前のバージョンの再構築モードとは互換性がありません。
imci_enable_add_column_instant_ddlパラメーターを OFF に設定する必要があります。また、テーブルにプライマリキーがあることを確認する必要もあります。
AutoIndex によって追加された列ストアインデックスの表示または削除方法
SELECT * FROM information_schema.imci_autoindex_executed;AutoIndex によって自動的に追加された列ストアインデックスを削除する方法は、手動で追加されたものを削除する方法と同じです。
ALTER TABLE t1 comment 'columnar=0';列ストアインデックス追加後に ALTER TABLE を使用した列の追加または削除に時間がかかる理由
列を追加または削除すると、通常、テーブルデータが再構築されます。元のテーブルに列ストアインデックスがある場合、インデックスデータもテーブルデータと一緒に再構築する必要があります。列ストアインデックスデータを再構築するプロセスでは、Redo ログへの書き込みが必要です。列ストアインデックスは通常、多くの列をカバーするため、生成される Redo ログデータの量は元のテーブルデータのサイズに比例します。これにより、列ストアインデックスのないテーブルを再構築する場合と比較して I/O データ量が増加し、実行時間が長くなります。
列ストアインデックスの追加による書き込みパフォーマンスへの影響
列ストアインデックスの追加が書き込みパフォーマンスに与える影響は、一般的に 5% 以内です。Sysbench oltp_insert ワークロード テストセットを使用したテストでは、列ストアインデックスを追加した後、書き込みパフォーマンスが約 3% 低下しました。
IMCI 機能がサポートするトランザクション分離レベル
列ストアインデックスは、READ_COMMITTED と REPEATABLE_READ の 2 つのトランザクション分離レベルをサポートしています。
REPEATABLE_READ トランザクション分離レベルの場合、IMCI 機能を使用する際には、列ストア読み取り専用ノードのみを含むカスタムエンドポイントを使用する必要があります。
PolarDB for MySQL 8.0.1.1.40 以降、および 8.0.2.2.21 以降のバージョンでは、Metabase BI などの一部のエコシステムツールが、クエリセッションでトランザクション分離レベルを READ_UNCOMMITTED などのサポートされていないレベルに暗黙的に設定する場合があります。このような場合は、
SET imci_ignore_unsupported_isolation_level=ONを実行して、強制的に READ_COMMITTED を使用できます。または、ODBC/JDBC 接続文字列にセッション変数の設定を追加することもできます。たとえば、Metabase では、接続文字列にsession Variables=imci_ignore_unsupported_isolation_level='ON'を追加できます。
列ストアインデックスはあいまい検索を高速化するか
はい。列ストアインデックスは、あいまい検索シナリオの高速化において非常に優れたパフォーマンスを発揮します。LIKE PRUNER、NGRAM LIKE、SMID LIKE などの機能をサポートしています。列ストアフルテキストインデックス機能も、あいまい検索の高速化を提供します。