Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

SQL クエリ・プランの解釈

この章では、クエリプランの表示によって生成される SQL クエリ・アクセス・プランで使用される言語および用語について解説します。

マップに格納されるテーブル

SQL テーブルは、一連のマップとして格納されます。各テーブルには、テーブル内のすべてのデータが含まれたマスタ・マップと、場合によっては、インデックス・マップやビットマップなどのその他のマップがあります。各マップは多次元グローバルとして示すことができます。これには、1 つ以上の添え字の一部のフィールド用のデータと、ノード値に格納された残りのフィールドがあります。添え字はアクセスされるデータを制御します。

  • マスタ・マップでは、通常、RowId フィールドや IDKEY フィールドはマップの添え字として使用されます。

  • インデックス・マップでは、通常、その他のフィールドは先頭の添え字として使用され、RowId フィールドや IDKEY フィールドは追加の下位レベルの添え字として使用されます。

  • ビットマップでは、ビットマップ・レイヤは追加の RowId の添え字レベルと見なされます。ただし、ビットマップは、RowId が正の整数である場合しか使用できません。

プランの開発

SQL クエリをコンパイルすることで、そのクエリによって指定されるデータへのアクセスや返送のための一連の命令が生成されます。これらの命令は、.INT ルーチンで ObjectScript コードとして表されます。

それらの命令およびその命令の実行シーケンスは、そのクエリに含まれるテーブルの構造や内容に関する SQL コンパイラの所有データの影響を受けます。コンパイラは、テーブル・サイズや使用可能なインデックスなどの情報を使用して、その一連の命令をできる限り効率化しようとします。

クエリ・アクセス・プラン (ShowPlan) は、その命令の結果セットを人が読める形式に変換したものです。クエリの設計者はこのクエリ・アクセス・プランを使用して、データへのアクセスがどのように行われるかを確認することができます。SQL コンパイラは、クエリによる指定に従って、データを最も効率的に使用できるようにしようとします。場合によっては、コンパイラが持つ情報よりも、クエリの設計者の方が格納されているデータの特定の側面について詳しいことがあります。その場合、設計者はクエリ・プランを利用して、元のクエリを変更することによって、クエリ・コンパイラにより多くの情報やガイダンスを提供することもできます。

プランの読み取り

“ShowPlan” の結果は、元のクエリで指定したデータにアクセスして提示するために実行される処理の内容を示す一連の文です。以下では、ShowPlan 文の解釈の仕方について説明します。

マップへのアクセス

クエリのプランはいくつかのテーブルにアクセスする可能性があります。テーブルにアクセスする際、プランは 1 つのマップ (インデックスまたはマスタ・マップ) にアクセスすることも、2 つのマップ (インデックス・マップとそれに続くマスタ・マップ)、あるいは、マルチ・インデックス・プランの場合はいくつかのマップにアクセスすることがあります。

マップを使用したデータへのアクセスでは、プランは使用される添え字を示します。また、実際の添え字値の内容 (添え字に対してテーブルに存在する単一の特定値、一連の特定値、値の範囲、またはすべての値のいずれか) も示します。どれが選択されるかは、クエリで指定されている条件によって異なります。明らかに、アクセスする添え字値が単一もしく少数である方が、その添え字レベルのすべての値にアクセスするよりも速く処理されます。

条件および式

クエリの実行時には、クエリで指定されているさまざまな条件がテストされます。前述のような添え字による制限などの特定の条件を除き、ShowPlan ではその出力としてテストの条件が明示的に示されることはありません。できるだけ早期に条件をテストすることをお勧めします。多様な条件をテストするために最適な場所は、プランの詳細から推測できます。

同様に、ShowPlan では式および部分式の計算の詳細は示されません。簡潔性は別にして、その主な理由はほとんどのデータベース環境で、テーブルおよびインデックスのアクセスが処理にとってより重要な側面となるためです。ディスク・アクセス速度が依然 CPU 処理よりも桁違いに遅いので、テーブル・データの取得にかかる負荷がクエリ全体の負荷の大半を占めています。

ループ

テーブルのデータにアクセスする際は、複数の行を繰り返し検証する必要性が多くなります。そのようなアクセスは、ループによって示されます。受け渡しごとに実行される命令は、ループの本文と呼ばれます。それらはインデントされることによって視覚的に示されます。複数のテーブルが関係するデータベース・アクセスでは、ループ内にループが必要となることが一般的です。この場合、各ループ・レベルは前のレベルからさらにインデントされることによって示されます。

一時ファイル

定義

クエリ・プランは、中間一時ファイル (一時ファイル) を作成して使用する必要性を示す場合もあります。これは、ローカル配列内の “スクラッチ” 領域となります。これは並べ替えなどのさまざまな目的で一時的な結果を保存するのに使用されます。マップと同様に、一時ファイルは 1 つ以上の添え字 (場合によっては、ノード・データも) を使用します。

使用

一時ファイルには、単一テーブルの処理からのデータが含まれる場合があります。この場合、一時ファイルの作成は、そのテーブル内のデータの事前処理と見なされることもあります。そのような一時ファイルの読み取りの後には、ソース・テーブルのマスタ・マップへのアクセスが行われる場合とそうでない場合があります。これ以外の場合、一時ファイルには複数のテーブルの処理の結果が含まれる可能性があります。さらに別の状況では、一時ファイルは分類された集約値の格納や DISTINCT のチェックなどに使用されます。

モジュール

一時ファイルの作成もその他の処理と同じく、モジュールと呼ばれる独立した作業ユニットで行われる場合があります。各モジュールには名前が付けられます。別々のモジュールがリストされている場合、プランは、各モジュールの呼び出し元を示しています。モジュールの実行が終了すると、処理がモジュールの呼び出しの直後の文から再開されます。

処理のために送信されるクエリ

リンクされたテーブルの場合、プランはリモートの SQL ゲートウェイ接続に送信中のクエリのテキストを示し、リモート・テーブルから要求データを取得します。

並列のクエリ処理では、プランは並列処理されるため送信中にある各種のクエリを示します。

サブクエリ、JOIN、および UNION

特定のクエリ内のサブクエリ (およびビュー) にも、個別に処理されるものがあります。そのプランは、独立したサブクエリ・セクションで示されます。サブクエリ・セクションの呼び出し元の正確な場所は、プランには示されません。それは、これらが条件または式の処理の一部として呼び出されることが多いためです。

OUTER JOIN を指定するクエリでは、外部結合の意味の要件を満たすために一致する行が見つからない場合に、プランでは NULL の行が生成される可能性が示される場合があります。

UNION の場合は、そのプランに、別個のモジュールにおけるさまざまな UNION のサブクエリからの結果行の組み合わせが示される場合があります (このモジュールでは、それらの結果行のさらなる処理が行われることがあります)。

プランの解析

特定のクエリのプランを解析する際に、アプリケーション開発者が別のプランの方が有効なのではと感じることもあります。アプリケーション開発者は、さまざまな方法でプランに影響を与えることができます。

とりわけ、実際のアプリケーション・データを含めた環境での TuneTable()Opens in a new tab の適切な実行により、プランは影響を受けます。クラス・ソース定義内の EXTENTSIZE テーブル、SELECTIVITY フィールド、および BlockCount マップなど、通常は TuneTable() が計算する値のいくつかを手動で定義することで目的のプランを達成することもできます。このドキュメントの “テーブルの最適化” の章の "テーブルのチューニング機能を使用する" を参照してください。

また、プランの分析により、ある変更をクラス定義に加えるとより効率的なプランとなることが判明する場合があります。以下に例を示します。

インデックスの追加

場合によっては (常にではありません)、事前処理のための一時ファイルの使用について、一時ファイルと同じまたは似た構造のインデックスを元のテーブルに追加すると、一時ファイルの構築が不要になることがあります。クエリ・プランからこの処理手順を削除することで、明らかにクエリの実行がより高速になる場合がありますが、テーブルの更新時にインデックスを保守するために必要な作業量とのバランスをとる必要があります。インデックスの作成の詳細は、このドキュメントの "インデックスの定義と構築" の章を参照してください。

インデックス・データへのフィールド追加

プランがインデックス使用中であることを示し、後にマスタ・マップへのアクセスが続く場合、このことはクエリで使用中のマスタ・マップ・フィールドをインデックス・ノード・データに追加することが、このクエリのプランの高速化へつながる場合があることを示唆しています。ここでも、更新時間の増加とのバランスをとる必要があります。また、このインデックスは大きく、読み取りにかかる時間が長くなるため、このインデックスを使用する他のクエリの処理に余分な時間がかかるようになります。

結合インデックスの追加

特定の順序で 2 つのテーブルが結合されているプランの場合 (例えば、まず t1 が取得され、次に、結合条件 t1.a=t2.b を使用してそれが t2 に結合されている場合)、逆のテーブル順序の方が高速なプランとなることがあります。例えば、t2 に、修飾行の数を大幅に限定する条件が追加されている場合です。このような場合、t1.a で t1 インデックスを追加することにより、そのような結合順序を考慮することができるようになります。インデックスの作成の詳細は、このドキュメントの "インデックスの定義と構築" の章を参照してください。

FeedbackOpens in a new tab