このトピックでは、PolarDB for MySQL のインメモリー列指向インデックス (IMCI) 機能に関するよくある質問にお答えします。
PolarDB for MySQL の IMCI 機能の使用方法
IMCI を使用してクエリを高速化するには、次の手順を実行します。
-
PolarDB for MySQL クラスターに読み取り専用 IMCI ノードを追加します。ノードを追加する際は、IMCI 機能を有効にしてください。手順については、「読み取り専用 IMCI ノードの追加」をご参照ください。
-
より高速なクエリパフォーマンスが必要なテーブルに IMCI を作成します。
CREATE TABLEまたはALTER TABLEステートメントを使用し、テーブルのCOMMENTフィールドにCOLUMNAR=1を追加します。IMCI の準備が完了すると、オプティマイザはクエリコストに基づいて IMCI を使用するかどうかを自動的に決定します。構文の詳細については、「テーブル作成時の IMCI の作成」をご参照ください。 -
SQL クエリを読み取り専用 IMCI ノードにルーティングします。オプティマイザは、クエリコストが特定のしきい値を超えるクエリに対して、IMCI を自動的に使用します。クエリの自動および手動ルーティングの詳細については、「クラスターエンドポイントを設定して行ストアノードと IMCI ノード間でトラフィックを分割する」をご参照ください。
IMCI のステータスの確認方法
ALTER TABLE ステートメントを使用して既存のテーブルに IMCI を追加した後、インデックスは読み取り専用 IMCI ノード上で非同期に構築されます。ステータスを確認するには、リクエスト分散が有効になっているクラスターエンドポイント経由でデータベースに接続するか、読み取り専用 IMCI ノードに直接接続します。その後、INFORMATION_SCHEMA.IMCI_INDEXES テーブルをクエリできます。IMCI がクエリに利用可能になるのは、そのステータスが COMMITTED になったときのみです。IMCI の構築の進捗を監視するには、INFORMATION_SCHEMA.IMCI_ASYNC_DDL_STATS テーブルをクエリします。詳細については、「インデックスステータスの表示」をご参照ください。
Data Management Service (DMS) を使用してデータベースにログインする場合、デフォルトではプライマリクラスターエンドポイントに接続されます。別のクラスターエンドポイントに接続するか、読み取り専用 IMCI ノードに直接接続するには、以下の手順に従ってください。
-
クラスターエンドポイントに接続します。
データ管理サービス (DMS) 5.0 コンソールにログインします。[インスタンスの追加] ページで、[エントリ方法] を [接続文字列] に設定し、クラスターエンドポイント を入力します。詳細については、「クラウドデータベースインスタンスの追加」をご参照ください。
-
読み取り専用 IMCI ノードに直接接続します。
まず、カスタムクラスターエンドポイントを作成し、対象の 読み取り専用 IMCI ノード のみを含むようにします。 次に、Data Management Service (DMS) 5.0 コンソールにログインします。 [インスタンスの追加] ページで、[接続方法] を 接続文字列 に設定し、読み取り専用 IMCI ノード の カスタムクラスターエンドポイント を入力します。 詳細については、「クラウドデータベースインスタンスを追加する」をご参照ください。
IMCI の使用状況の確認と実行計画の表示
EXPLAIN ステートメントを使用して、クエリの実行計画を表示します。出力に IMCI Execution Plan が表示されていれば、IMCI によってクエリが高速化されたことを示します。以下に例を示します。
*************************** 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)
IMCI を使用するクエリの実行計画はツリー状の構造であり、各レベルがオペレーターを表します。通常、各オペレーターは SQL クエリ内の操作に対応します。たとえば、CTableScan オペレーターはテーブルをスキャンし、HashJoin オペレーターは JOIN 句に、HashGroupby オペレーターは GROUP BY 句に対応します。ただし、Sequence などの一部のオペレーターは、クエリの最適化プロセス中に生成されるため、元のクエリ内の操作には直接マッピングされません。
IMCI が使用されないクエリのトラブルシューティング
IMCI がクエリを高速化するのは、いくつかの条件が満たされた場合のみです。具体的には、クエリ対象のテーブルに IMCI が存在すること、クエリの推定コストが特定のしきい値を超えること、そしてクエリが読み取り専用 IMCI ノードにルーティングされることです。クエリで IMCI が使用されていない場合は、以下のトラブルシューティング手順に従ってください。
-
クエリが読み取り専用 IMCI ノードにルーティングされていることを確認してください。
SQL 監査と分析機能を使用して、クエリが読み取り専用 IMCI ノードにルーティングされたことを確認してください。
トラフィックの自動分割が有効な クラスターエンドポイント を使用する場合、PolarProxy は、推定コストが
imci_ap_threshold値よりも高いクエリを 読み取り専用 IMCI ノードに自動的にルーティングします。 また、SELECTキーワードの前に/*FORCE_IMCI_NODES*/ヒントを追加することで、クエリを 読み取り専用 IMCI ノードに強制的にルーティングすることもできます。 例:/*FORCE_IMCI_NODES*/EXPLAIN SELECT COUNT(*) FROM t1 WHERE t1.a > 1;詳細については、「自動トラフィック分割の設定」をご参照ください。
説明クエリが常に読み取り専用 IMCI ノードにルーティングされるようにするには、そのノードに直接接続する新しいエンドポイントを作成してください。
-
クエリコストがしきい値を超えているか確認してください。
読み取り専用 IMCI ノードでは、オプティマイザがクエリのコストを見積もります。見積もられたコストが
cost_threshold_for_imciパラメーターよりも高い場合、クエリは IMCI を使用します。それ以外の場合は、標準の行インデックスを使用します。クエリが 読み取り専用 IMCI ノードにルーティングされたことを確認した後も、実行計画に IMCI の使用が表示されない場合は、推定 クエリコストが低すぎることが原因である可能性があります。
Last_query_cost_for_imci変数を表示して、最後に実行されたクエリの推定コストを確認します。EXPLAIN SELECT * FROM t1; SHOW STATUS LIKE 'Last_query_cost_for_imci';SQL 文の推定実行コストが、プリセットの
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; -
クエリで使用されるすべての列が IMCI でカバーされているか確認してください。
組み込みストアドプロシージャ
dbms_imci.check_columnar_index()を使用して、クエリ内のテーブルに IMCI が作成されているかどうかを確認します。 例:CALL dbms_imci.check_columnar_index('SELECT COUNT(*) FROM t1 WHERE t1.a > 1');クエリが IMCI でカバーされていない列を参照している場合、ストアドプロシージャはカバーされていないテーブルと列のリストを返します。すべての列がカバーされている場合、プロシージャは空の結果セットを返します。
-
サポートされていない SQL 機能がないか確認してください。
制限事項を参照し、クエリ内のすべての機能が IMCI でサポートされていることを確認してください。
これらのチェックがすべて通れば、クエリは IMCI を使用するはずです。
読み取り専用 IMCI ノードは行インデックスを使用できるか
はい。 読み取り専用 IMCI ノードは、IMCI 機能が有効化された標準の読み取り専用ノードです。 したがって、IMCI と標準の行インデックスの両方を使用できます。 オプティマイザは、cost_threshold_for_imci の値に基づいて、どちらのインデックスを使用するかを選択します。
ヒントを使用して単一クエリのクエリコストしきい値を設定し、強制的に IMCI を使用するよう指定できます。
SELECT /*+ SET_VAR(cost_threshold_for_imci=0) */ COUNT(*) FROM t1 WHERE t1.a > 1;
同様に、クエリが IMCI を使用しないように強制することもできます。
SELECT /*+ SET_VAR(USE_IMCI_ENGINE=OFF) */ COUNT(*) FROM t1 WHERE t1.a > 1;
クエリに適した IMCI の作成方法
クエリで IMCI を使用するには、そのクエリが参照するすべての列が IMCI でカバーされている必要があります。一部の列がカバーされていない場合は、CREATE TABLE 文または ALTER TABLE 文を使用して、それらを IMCI に追加できます。PolarDB for MySQL には、このプロセスに役立ついくつかの組み込みストアドプロシージャが用意されています。
dbms_imci.columnar_advise() ストアドプロシージャを使用して、特定のクエリに必要な DDL ステートメントを生成します。 この DDL ステートメントを使用して IMCI を作成すると、クエリ内のすべての列がカバーされることが保証されます。 詳細については、「IMCI を作成するための DDL ステートメントを取得する」をご参照ください。
dbms_imci.columnar_advise('<query_string>');
Multi-primary Cluster (Limitless) を使用している場合、このストアドプロシージャをグローバル読み取り専用ノードで実行する必要があります。 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 ステートメントを取得します。 詳細については、「IMCI 作成用 DDL ステートメントの一括取得」をご参照ください。
PolarDB for MySQL IMCIは、単一ノードの並列クエリをサポートしていますか。サポートしている場合、どのようにして特定の SQL クエリの並列度をカスタマイズできますか。
単一ノードでの並列クエリは、デフォルトで有効です。EXPLAIN を実行して実行計画を表示すると、max_dop フィールドに実際に使用された並列度が表示されます。特定のクエリの並列度をカスタマイズするには、クエリを実行する前にセッションレベルで imci_max_dop パラメーターを設定できます。たとえば、
set imci_max_dop=8; explain select xxxx
高いリソース使用率と監視
-
デフォルトでは、IMCI は単一のクエリを並列実行するように設定されており、利用可能なすべての CPU リソースを使用する可能性があります。複数のクエリが同時に実行される場合、内部データベーススケジューラは、各クエリの CPU とメモリの制限を動的に削減してリソースを管理します。その結果、読み取り専用 IMCI ノードの平均 CPU およびメモリ使用率は、通常、他のノードよりも高くなります。
imci_max_dopパラメーターを調整することで、単一クエリの最大並列度 (最大 CPU コア数) を制御できます。 -
CPU 使用率の監視アラートしきい値は 70%、メモリ使用率は 90% に設定することを推奨します。
-
PolarDB for MySQL では、同一クラスター内の異なるノードで異なる仕様を使用できます。読み取り専用 IMCI ノードを独立してスケールアップまたはスケールダウンできます。読み取り専用 IMCI ノードには、少なくとも 8 コア CPU と 16 GB のメモリを搭載することを推奨します。
PolarDB for MySQL 5.6/5.7 での IMCI のサポート
いいえ。PolarDB for MySQL 5.6 または 5.7 では IMCI 機能はサポートされていません。PolarDB for MySQL 8.0 以降のバージョンでのみサポートされています。
IMCI の制限事項と MySQL との互換性
IMCI は MySQL の構文と完全に互換性があります。ただし、特定の空間データ型表現、フルテキストインデックス、一部の形式の相関サブクエリなど、あまり一般的でない一部のクエリ機能はまだ完全にはサポートされていません。これらの機能を使用するクエリは IMCI によって高速化されず、自動的に標準の行インデックスにフォールバックします。制限事項の詳細なリストについては、「制限事項」をご参照ください。
INSERT/CREATE AS SELECT での IMCI の使用
IMCI は読み取り専用ノード上のクエリにのみ使用できますが、INSERT および CREATE ステートメントはプライマリノードでのみ実行できます。 このため、INSERT INTO SELECT または CREATE TABLE AS SELECT ステートメントの SELECT 部分を高速化するには、IMCI ETL 機能を使用する必要があります。 詳細については、「IMCI を使用した ETL の高速化」をご参照ください。
価格と料金
IMCI 機能自体は無料です。ただし、これを使用するには、IMCI が有効になっている専用の読み取り専用ノードを追加する必要があります。この新しい読み取り専用ノードと、作成した IMCI が消費する追加ストレージに対して課金されます。
標準の読み取り専用ノードは IMCI をサポートしていません。
ストレージ要件
IMCI はデータを列形式で保存するため、高い圧縮率を実現します。行ベースのストレージと比較して、IMCI は 3:1 から 10:1 の圧縮率を達成でき、通常、追加のストレージフットプリントは元のテーブルサイズの 10% から 30% にとどまります。
IMCI のストレージ使用量の表示
-
PolarDB for MySQL クラスターバージョン 8.0.1.1.32 以前では、
information_schemaのimci_columnsシステムテーブルを照会して、IMCI を使用するテーブルのストレージ領域と圧縮率を表示します。 たとえば、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 ステートメントを実行します。-
IMCI を持つ
testテーブルが使用するストレージ領域を表示します: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'; -
列の圧縮率を表示します。
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 |
圧縮後の列データのサイズ (バイト単位)。 説明
このパラメーターは、PolarDB for MySQL 8.0.1.1.33 より前のバージョンに適用されます。 |
|
CMP_DATA_SIZE |
圧縮後の列データのサイズ (バイト単位)。 説明
このパラメーターは、PolarDB for MySQL 8.0.1.1.33 以降のバージョンに適用されます。 |
IMCI でのインスタント DDL
-
8.0.1.1.42 および 8.0.2.2.23 より前の PolarDB for MySQL バージョンでは、テーブルレベルの IMCI を持つテーブルに列を追加する操作は、インスタント DDL ロジックを使用しません。これは、操作が IMCI 構造の変更とインデックスデータの再構築を必要とするためです。
-
PolarDB for MySQL 8.0.1.1.42 以降、および 8.0.2.2.23 以降では、テーブルレベルの IMCI を持つテーブルでインスタント DDL がサポートされています。この機能は、以前のバージョンの再構築モードとは互換性がありません。
imci_enable_add_column_instant_ddlパラメーターを ON に設定し、テーブルにプライマリキーがあることを確認する必要があります。
自動作成された IMCI の表示または削除
SELECT * FROM information_schema.imci_autoindex_executed;
autoindex によって作成された IMCI の削除プロセスは、手動で作成されたものと同じです。
ALTER TABLE t1 comment 'columnar=0';
IMCI 使用時の ALTER TABLE のパフォーマンス
列の追加または削除は、通常、テーブルデータの再構築を伴います。テーブルに IMCI がある場合、IMCI データも再構築する必要があります。この再構築プロセスは Redo ログに書き込みます。IMCI は多くの場合、多数の列をカバーするため、生成される Redo ログデータの量は元のテーブルデータのサイズに比例します。これにより、IMCI のないテーブルを再構築する場合と比較して I/O 量が多くなり、操作に時間がかかります。
書き込みパフォーマンスへの影響
IMCI の作成が書き込みパフォーマンスに与える影響は最小限で、通常は 5% 未満です。oltp_insert workload を使用した Sysbench テストでは、IMCI の作成後に約 3% のパフォーマンス低下が見られます。
サポートされているトランザクション分離レベル
IMCI は、READ_COMMITTED および REPEATABLE_READ のトランザクション分離レベルをサポートしています。
-
REPEATABLE_READトランザクション分離レベルで IMCI を使用するには、読み取り専用 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'を追加できます。
あいまいクエリの高速化
はい。IMCI はあいまいクエリのユースケースを大幅に高速化し、LIKE PRUMER、NGRAM LIKE、SMID LIKE などの操作をサポートします。さらに、列指向フルテキストインデックス機能もあいまいクエリのユースケースの高速化に役立ちます。