このオプション・キーワードを指定すると、クエリ・オプティマイザは指定されたインデックス、またはインデックスのリストを無視します (同義の %IGNOREINDICES は非推奨ですが、下位互換性保持のためにサポートされます)。
このキーワードに続いて、1 つ以上のインデックス名を指定します。複数のインデックス名はコンマで区切る必要があります。インデックス名は、以下の形式のいずれかを使用して指定できます。
%IGNOREINDEX [[schemaname.]tablename.]indexname [,...] %IGNOREINDEX [[schemaname.]tablename.]* [,...]
schemaname と tablename は省略可能です。省略した場合は、現在の既定のスキーマ、および FROM table-ref として指定されたテーブル名が使用されます。アスタリスク (*) ワイルドカードを使用すると、指定したテーブルのインデックス名がすべて指定されます。インデックス名は順不同で指定できます。InterSystems SQL は指定されたインデックス名 (またはその schemaname および tablename) を検証しません。存在しない、または重複するインデックス名は単に無視されます。
この最適化制約を使用すると、特定のクエリに対して最適ではないインデックスを使用しないよう、クエリ・オプティマイザに指定することができます。1 つを除くすべてのインデックス名を指定することで、事実上、クエリ・オプティマイザで残りのインデックスを使用するよう強制できます。
また、最初に %NOINDEX キーワードで条件を記述することで、特定の条件式で特定のインデックスを無視することができます。詳細は、"SQL 最適化ガイド" の “クエリ処理でのインデックスの使用” を参照してください。
%INORDER
このオプション・キーワードを指定すると、クエリ・オプティマイザは FROM 節にリストされるテーブルの順番で結合を実行します。コンパイル時間を最小限にします。矢印構文で参照されるテーブルの結合順には制限はありません (矢印構文の使用法の詳細は、"InterSystems SQL の使用法" の "暗黙結合" を参照してください)。サブクエリを平坦化しても、インデックスを使用しても、影響を受けることはありません。
%INORDER は、CROSS JOIN または RIGHT OUTER JOIN で使用することはできません。指定されたテーブル順が外部結合に必要な順番と一致しない場合、SQLCODE -34 エラーである "オプティマイザが使用可能な結合順序を見つけることができませんでした" が生成されます。これを避けるために、外部結合で使用する場合は、%INORDER のみを ANSI 形式の左外部結合または FULL 外部結合で使用することをお勧めします。
シャード・テーブルに対してクエリを実行するときに %INORDER を使用することはできません。"スケーラビリティ・ガイド" の “シャーディングによるデータ量に応じた InterSystems IRIS の水平方向の拡張” の章にある "シャード・クラスタにおけるクエリ" を参照してください。
ビューとテーブル・サブクエリは、FROM 節で指定された順番で処理されます。
このキーワードと %FIRSTTABLE および %STARTTABLE を比べた場合、2 つは完全な結合順序でなく最初の結合テーブルのみを指定する点が異なります。さまざまな結合順序の最適化によるテーブルのマージの動作については、"%STARTTABLE" を参照してください。
%INORDER の最適化と %PARALLEL の最適化は同時に使用できません。両方を指定すると、%PARALLEL は無視されます。
%NOFLATTEN
このオプションのキーワードは、ブーリアン値を返すサブクエリである修飾付きサブクエリの FROM 節で指定します。これにより、コンパイラ・オプティマイザでサブクエリの平坦化を抑制する必要があることを指定します。この最適化オプションは、サブクエリをクエリに効果的に統合して修飾付きサブクエリを含むクエリを最適化する “平坦化” (既定) を無効にします。この平坦化では、サブクエリのテーブルをクエリの FROM 節に追加し、サブクエリの条件をクエリの WHERE 節の結合または制限に変換します。
以下に、%NOFLATTEN を使用する修飾付きサブクエリの例を示します。
SELECT Name,Home_Zip FROM Sample.Person WHERE Home_Zip IN
(SELECT Office_Zip FROM %NOFLATTEN Sample.Employee)
SELECT Name,(SELECT Name FROM Sample.Company WHERE EXISTS
(SELECT * FROM %NOFLATTEN Sample.Company WHERE Revenue > 500000000))
FROM Sample.Person
%INORDER および %STARTTABLE の最適化では、暗黙的に %NOFLATTEN が指定されます。
%NOMERGE
このオプションのキーワードは、サブクエリの FROM 節で指定します。これにより、コンパイラ・オプティマイザではサブクエリをビューに変換しないことを指定します。この最適化オプションは、サブクエリを含むクエリの最適化を無効にします。この最適化では、サブクエリをインライン・ビューとしてクエリの FROM 節に追加し、クエリのフィールドに対するサブクエリの比較が、結合としてクエリの WHERE 節に移動します。
%NOREDUCE
このオプションのキーワードは、ストリーム化されたサブクエリの FROM 節で指定します。ここのサブクエリとは、行の結果セットを返すサブクエリ、つまりクエリに含まれる FROM 節内のサブクエリです。これは、コンパイラ・オプティマイザではサブクエリ (またはビュー) とそれを含むクエリとの結合を抑制する必要があるということを指定します。
以下の例では、クエリ・オプティマイザは、通常、Sample.Person とサブクエリとのデカルト積結合を実行することで、このクエリを “削減” します。%NOREDUCE 最適化オプションは、これを防止します。InterSystems IRIS は、代わりに gname に一時インデックスを構築し、この一時インデックスに結合を実行します。
SELECT * FROM Sample.Person AS p,
(SELECT Name||'goo' AS gname FROM %NOREDUCE Sample.Employee) AS e
WHERE p.name||'goo' = e.gname
%NOSVSO
このオプションのキーワードは、ブーリアン値を返すサブクエリである修飾付きサブクエリの FROM 節で指定します。これにより、コンパイラ・オプティマイザで集合値サブクエリの最適化 (SVSO) を抑制する必要があることを指定します。
ほとんどの場合、集合値サブクエリの最適化によって [NOT] EXISTS および [NOT] IN サブクエリのパフォーマンスが向上し、特に、1 つだけの分離可能な相関条件が指定されたサブクエリのパフォーマンスが向上します。SVSO はこのために、その条件を満たすデータ値を一時インデックスに移入します。そのサブクエリを繰り返し実行する代わりに、InterSystems IRIS はこれらの値を一時インデックス内で検索します。例えば、SVSO は、P.num の一時インデックスを作成することで、NOT EXISTS (SELECT P.num FROM Products P WHERE S.num=P.num AND P.color='Pink') を最適化します。
SVSO は、ALL または ANY キーワードが比較演算子 (>、>=、<、または <=) およびサブクエリと共に使用されているサブクエリ (例 : ...WHERE S.num > ALL (SELECT P.num ...)) を最適化します。これを行うには、サブクエリ式 sqbExpr (この例では P.num) を、適宜 MIN(sqbExpr) または MAX(sqbExpr) で置換します。これにより、sqbExpr に対するインデックスが存在する場合に高速な計算が実現されます。
%INORDER および %STARTTABLE の最適化では、集合値サブクエリの最適化が抑制されません。
%NOTOPOPT
このオプションのキーワードは、TOP 節を ORDER BY 節と共に使用する場合に指定します。既定では、TOP を ORDER BY と共に使用すると、最初の行に移動する時間が最速になるように最適化されます。%NOTOPOPT (TOP 最適化でない) を指定することでクエリが最適化され、完全な結果セットを最速で取得できるようになります。
%NOUNIONOROPT
このオプションのキーワードは、クエリまたはサブクエリの FROM 節で指定します。これにより、複数の OR 条件および UNION クエリ式に対するサブクエリに実行される自動最適化が無効化されます。これらの自動最適化では、適切な場合には、複数の OR 条件が UNION サブクエリに変換されたり、UNION サブクエリが OR 条件に変換されたりします。これらの UNION/OR 変換により、EXISTS やその他の下位の述語を InterSystems IRIS クエリ・オプティマイザ・インデックスで使用できる最上位の条件に移行できます。これらの既定の変換は、ほとんどの状況に適しています。
ただし、状況によってはこれらの UNION/OR 変換によって大幅なオーバーヘッドが生じることがあります。%NOUNIONOROPT を指定すると、この FROM 節に関連付けられた WHERE 節内のすべての条件に対して自動の UNION/OR 変換が無効になります。そのため、複雑なクエリでは、この自動 UNION/OR 最適化を 1 つのサブクエリにのみ無効にしてその他のサブクエリには有効にすることができます。
UNION %PARALLEL キーワードは、自動の UNION から OR への最適化を無効にします。
%INORDER および %STARTTABLE の最適化では、OR から UNION への最適化が抑制されますが、UNION から OR への最適化は抑制されません。
%PARALLEL
このオプションのキーワードは、クエリの FROM 節で指定します。これは、InterSystems IRIS が複数のプロセッサを使用してクエリの並列処理を実行することを示しています (該当する場合)。これにより、1 つ以上の COUNT、SUM、AVG、MAX、または MIN 集約関数または GROUP BY 節 (あるいはその両方) を使用するクエリや、他の多くのタイプのクエリで、パフォーマンスを大幅に向上させることができます。一般にこれらは、大量のデータを処理し、小規模な結果セットを返すクエリです。例えば、SELECT AVG(SaleAmt) FROM %PARALLEL User.AllSales GROUP BY Region は、並列処理を使用する可能性が高くなります。
個々のフィールドと集約関数の両方を指定しているが GROUP BY 節を含まないクエリは、並列処理を実行できません。例えば、SELECT Name,AVG(Age) FROM %PARALLEL Sample.Person は並列処理を実行しませんが、SELECT Name,AVG(Age) FROM %PARALLEL Sample.Person GROUP BY Home_State は並列処理を実行します。
%PARALLEL は、SELECT クエリとそのサブクエリで使用するためのものです。INSERT コマンド・サブクエリは %PARALLEL を使用できません。
%PARALLEL を指定すると、クエリによってはパフォーマンスが低下する可能性があります。複数の同時ユーザがいるシステム上で %PARALLEL を指定してクエリを実行すると、総合的なパフォーマンスが低下する可能性があります。
Note:
%PARALLEL を指定するクエリは、読み取り専用ではなく、読み取り/書き込み可能なデータベースで実行する必要があります。そうでないと、<PROTECT> エラーが発生する可能性があります。
FROM 節で %PARALLEL キーワードを指定していても、並列処理ではなく線形処理を使用するクエリがあります。特に列指向テーブルでは、DISTINCT、ORDER BY、TOP、UNION を使用するクエリは並列処理されません。また、最適化すると並列処理の利点を得られなくなるクエリもあります。並列処理のために InterSystems IRIS によってクエリが分割されたか、分割された場合はどのように分割されたかを、プラン表示を使用して確認できます。現在のシステム上のプロセッサ数を特定するには、%SYSTEM.Util.NumberOfCPUs()Opens in a new tab メソッドを使用します。
詳細は、"SQL 最適化ガイド" の "並列クエリ処理の構成" を参照してください。
%STARTTABLE
このオプション・キーワードを指定すると、クエリ・オプティマイザは FROM 節にリストされた最初のテーブルから結合を開始します。残りのテーブルの結合順序は、クエリ・オプティマイザに委任されます。このキーワードと %INORDER を比べた場合、%INORDER では完全な結合順序を指定する点が異なります。
%STARTTABLE は、CROSS JOIN または RIGHT OUTER JOIN で使用することはできません。%STARTTABLE (または %FIRSTTABLE) を使用して、LEFT OUTER JOIN の右側 (または RIGHT OUTER JOIN の左側) で結合順序を開始することはできません。指定された先頭テーブルが外部結合に必要なテーブルと一致しない場合、SQLCODE -34 エラーである "オプティマイザが使用可能な結合順序を見つけることができませんでした" が生成されます。これを避けるために、外部結合で使用する場合は、%STARTTABLE のみを ANSI 形式の左外部結合または FULL 外部結合で使用することをお勧めします。
以下の表に、%INORDER および %STARTTABLE の最適化によりスーパークエリの親とインライン・ビューを組み合わせる場合のマージの動作を示します。
|
結合オプティマイザを指定しないスーパークエリ |
%STARTTABLE を指定したスーパークエリ |
%INORDER を指定したスーパークエリ |
結合オプティマイザを指定しないビュー |
可能な場合にビューをマージする。 |
ビューがスーパークエリの先頭の場合、マージしない。
それ以外は、可能な場合にビューをマージする。 |
可能な場合にマージする。ビューの基本テーブルの順序は不規則になります。 |
%STARTTABLE を指定したビュー |
マージしない。 |
ビューがスーパークエリの先頭の場合、可能であればマージする。ビューの先頭テーブルはスーパークエリの先頭テーブルになります。
それ以外はマージしない。 |
マージしない。 |
%INORDER を指定したビュー |
マージしない。 |
マージしない。 |
ビューが %INORDER で制御されない場合、マージしない。
それ以外は、可能な場合にマージする。ビューの順序は、スーパークエリの結合順序に置き換えられます。 |
%FIRSTTABLE ヒントは、機能的には %STARTTABLE と同じですが、任意の順序で結合テーブル・シーケンスを柔軟に指定できます。
FROM 節におけるテーブル値関数
テーブル値関数は、ストアド・プロシージャとして投影される、単一の結果セットを返すクラス・クエリです。テーブル値関数は、SqlProc が TRUE であるクラス・クエリです。テーブル値関数として使用するクラス・クエリは、LOGICAL モードまたは RUNTIME モードのどちらかでコンパイルする必要があります。テーブル値関数として使用され、RUNTIME モードでコンパイルされている場合、そのテーブル値関数のクエリは、LOGICAL モードで呼び出されます。
テーブル値関数は、クラス・クエリのためのストアド・プロシージャ名と同じ名前付け規約に従います。パラメータの括弧は必須です。括弧は空にすることや、1 つのリテラルまたはホスト変数、あるいはリテラルおよびホスト変数のコンマ区切りのリストを囲むことができます。パラメータを指定しない場合 (空の括弧または Null 文字列)、テーブル値関数はすべてのデータ行を返します。
テーブル値関数を使用するクエリを発行するには、ユーザに、そのテーブル値関数を定義するストアド・プロシージャの EXECUTE 特権が必要になります。ユーザには、テーブル値関数のクエリでアクセスされるテーブルまたはビューに対する SELECT 特権も必要となります。
以下の例では、クラス・クエリ Sample.Person.ByName はストアド・プロシージャとして投影されます。これにより、テーブル値関数として使用できます。
SELECT Name,DOB FROM Sample.SP_Sample_By_Name('A')
以下のダイナミック SQL の例では、同じテーブル値関数を指定します。%Execute() メソッドを使用して ? 入力パラメータにパラメータ値を指定します。
SET myquery="SELECT Name,DOB FROM Sample.SP_Sample_By_Name(?)"
SET tStatement = ##class(%SQL.Statement).%New()
SET qStatus = tStatement.%Prepare(myquery)
IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
SET rset = tStatement.%Execute("A")
DO rset.%Display()
WRITE !,"End of A data",!!
SET rset = tStatement.%Execute("B")
DO rset.%Display()
WRITE !,"End of B data"
テーブル値関数は、SELECT 文または DECLARE 文の FROM 節でのみ使用できます。テーブル値関数名は、スキーマ名で修飾することも、未修飾 (スキーマ名なし) にすることもできます。未修飾の名前は、既定のスキーマを使用します。SELECT 文の FROM 節では、テーブル名を使用できる箇所ならどこでもテーブル値関数を使用できます。ビューまたはサブクエリでも使用でき、コンマ区切りのリストまたは明示的な JOIN 構文を使用して他の table-ref 項目に結合できます。
テーブル値関数は、INSERT、UPDATE、または DELETE 文で直接使用することはできません。ただし、テーブル値関数を指定するこれらのコマンドのためのサブクエリを指定することはできます。
InterSystems SQL は、テーブル値関数のための EXTENTSIZE、またはテーブル関数列のための SELECTIVITY は定義しません。
FROM 節のサブクエリ
FROM 節ではサブクエリを指定できます。これは、ストリーム化されたサブクエリとして知られています。サブクエリは、JOIN 構文での使用や AS キーワードを使用したオプションのエイリアス割り当てなども含めて、テーブルと同様に扱われます。FROM 節には、複数のテーブル、ビュー、およびサブクエリを任意の組み合わせで含むことができますが、"JOIN" で説明されている JOIN 構文の制約を受けます。
サブクエリは括弧で囲まれます。以下の例は、FROM 節のサブクエリを示しています。
SELECT name,region
FROM (SELECT t1.name,t1.state,t2.region
FROM Employees AS t1 LEFT OUTER JOIN Regions AS t2
ON t1.state=t2.state)
GROUP BY region
サブクエリでは TOP 節を指定できます。サブクエリには、TOP 節と組み合わせて ORDER BY 節を記述できます。
サブクエリでは SELECT * 構文を使用できます。ただし、FROM 節から得られるのは数値としての式なので、SELECT * を指定したサブクエリでは 1 つの列のみが生成されるようにする必要があります。
サブクエリ内の結合を NATURAL 結合にしたり、USING 節を指定することはできません。
FROM サブクエリと %VID
FROM サブクエリが呼び出されると、このサブクエリは、返されるサブクエリ行ごとに %VID を返します。%VID は整数カウンタ・フィールドです。その値は、システムによって割り当てられる一意の非 NULL かつ非ゼロ値であり、変更することはできません。%VID は、明示的に指定された場合にのみ返されます。これはデータ型 INTEGER として返されます。%VID の値は連続した整数であるため、サブクエリが順序付きデータを返す場合はとても有意義なものになります。TOP 節と組み合わせるときには、サブクエリでは ORDER BY 節以外は使用できません。
%VID は連続した整数であるため、%VID を使用して、ORDER BY 節が使用されたサブクエリ内の項目のランキングを特定できます。以下の例では、最も新しい 10 件のレコードが Name の順にリストされますが、それらのタイムスタンプ・ランキングは %VID の値を使用して簡単に確認できます。
SELECT Name,%VID,TimeStamp FROM
(SELECT TOP 10 * FROM MyTable ORDER BY TimeStamp DESC)
ORDER BY Name
%VID の一般的な用途の 1 つは、実行内容を 1 つの表示ウィンドウに収まる行数に合致する連続したサブセットに分割して、結果セットを “ウィンドウ表示” することです。例えば、20 件のレコードを表示してから、ユーザが Enter キーを押すまで待ち、次の 20 件のレコードを表示できます。
以下の例は、%VID を使用して、結果を 10 件のレコードごとのサブセットに分割して “ウィンドウ表示” します。
set myq=4
set myq(1)="SELECT %VID,* "
set myq(2)="FROM (SELECT TOP 60 Name,Age FROM Sample.Person "
set myq(3)="WHERE Age > 55 ORDER BY Name) "
set myq(4)="WHERE %VID BETWEEN ? AND ?"
set tStatement = ##class(%SQL.Statement).%New()
set qStatus = tStatement.%Prepare(.myq)
if $$$ISERR(qStatus) {write "%Prepare failed:" do $SYSTEM.Status.DisplayError(qStatus) quit}
for i=1:10:60 {
set rset = tStatement.%Execute(i,i+9)
if (rset.%SQLCODE '= 0) {write "%Execute failed:", !, "SQLCODE ", rset.%SQLCODE, ": ", rset.%Message quit}
while rset.%Next()
{
do rset.%Print()
}
if (rset.%SQLCODE < 0) {write "%Next failed:", !, "SQLCODE ", rset.%SQLCODE, ": ", rset.%Message quit}
}
write "End of data"
%VID の使用の詳細は、"InterSystems SQL の使用法" の "ビューの定義と使用" の章を参照してください。
LATERAL キーワード
FROM 節で以前に指定したテーブルのフィールド値をビューおよびテーブル値関数で参照できるようにすることで、LATERAL キーワードを使用して FROM 処理の順序をより明示的に制御できます。このようなラテラル参照は、サブクエリまたはテーブル値関数で生成する行に影響します。
LATERAL キーワードを指定したサブクエリまたはテーブル値関数では、ラテラル参照するフィールドが指定値と見なされます。ラテラル参照先のフィールドは、必ず同じ FROM 節にある以前の FROM アイテムから得られます。
FROM サブクエリに先行して記述した LATERAL キーワードは、クエリの中で意味的に先行する FROM アイテムのフィールドを、このサブクエリが参照する可能性があることを示します。このようなラテラル参照先のフィールドは、LATERAL が指定された FROM サブクエリよりも先に処理されます。
テーブル値関数に先行して記述した LATERAL キーワードは、以前の FROM アイテムのフィールドを、テーブル値関数で使用できることを示しています。このコンテキストでは、このキーワードはオプションであり、このような参照をテーブル値関数で使用するとラテラル結合が暗黙的に適用されます。
オプションの FROM 節
SELECT 項目リストで (直接的にも間接的にも) テーブル・データが参照されていない場合、FROM 節はオプションです。この種類の SELECT は、関数、演算子式、定数またはホスト変数からデータを返す場合に使用できます。テーブル・データを参照しないクエリでは、以下のようになります。
-
FROM 節が省略された場合には、TOP キーワードの値に関係なく、返されるデータ行は最大でも 1 つです。TOP が 0 の場合には、データが返されません。DISTINCT 節は無視されます。特権は不要です。
-
FROM 節を指定する場合には、現在のネームスペースに既存のテーブルを指定する必要があります。そのテーブルが参照されない場合でも、テーブルに SELECT 特権を設定する必要があります。TOP 節または DISTINCT 節を指定した場合、あるいはその節を WHERE 節または HAVING 節で制限した場合を除き、返される同一データ行の数は、指定したテーブルの行数と等しくなります。DISTINCT 節を指定すると、出力が単一のデータ行に限定されます。TOP キーワードを指定すると、出力は TOP 値で指定された行数に制限されます。TOP が 0 の場合には、データが返されません。
FROM 節を使用した場合でも使用しない場合でも、後続の節 (WHERE、GROUP BY、HAVING または ORDER BY) は指定できます。結果を返すかどうか、または同一の結果行をいくつ返すかを決定する場合には、WHERE 節または HAVING 節を使用できます。FROM 節を指定していない場合でも、これらの節はテーブルを参照できます。GROUP BY 節または ORDER BY 節を指定することもできますが、これらの節は無意味です。
以下は、テーブル・データを参照しない SELECT 文の例です。どちらの例も、情報を 1 行返します。
以下の例では、FROM 節が省略されています。DISTINCT キーワードは不要ですが、指定することはできます。SELECT 節は許可されていません。
SELECT 3+4 AS Arith,
{fn NOW} AS NowDateTime,
{fn DAYNAME({fn NOW})} AS NowDayName,
UPPER('MixEd cASe EXPreSSioN') AS UpCase,
{fn PI} AS PiConstant
以下の例では、FROM 節が含まれています。DISTINCT キーワードは、1 つのデータ行を返すために使用されています。FROM 節で参照するテーブルは、有効なテーブルである必要があります。ここでは ORDER BY 節が許可されていますが無意味です。ORDER BY 節では、有効な選択項目の別名を指定する必要があります。
SELECT DISTINCT 3+4 AS Arith,
{fn NOW} AS NowDateTime,
{fn DAYNAME({fn NOW})} AS NowDayName,
UPPER('MixEd cASe EXPreSSioN') AS UpCase,
{fn PI} AS PiConstant
FROM Sample.Person
ORDER BY NowDateTime
以下の例は両方とも、結果を返すかどうかを決定するために WHERE 節を使用しています。最初の例では FROM 節が含まれており、DISTINCT キーワードを使用して 1 つのデータ行を返します。2 番目の例では FROM 節が省略されているため、返されるデータ行は最大でも 1 つです。どちらの場合でも、WHERE 節で参照するテーブルは、SELECT 特権を設定した有効なテーブルである必要があります。
SELECT DISTINCT
{fn NOW} AS DataOKDate
FROM Sample.Person
WHERE FOR SOME (Sample.Person)(Name %STARTSWITH 'A')
SELECT {fn NOW} AS DataOKDate
WHERE FOR SOME (Sample.Person)(Name %STARTSWITH 'A')
関連項目
-
SELECT
-
JOIN
-
"InterSystems SQL の使用法" の “データベースの問い合わせ” の章
-
"InterSystems SQL の使用法" の “テーブルの定義” の章
-
"SQL 最適化ガイド" の “SQL 文と SQL 統計の分析”
-
"InterSystems IRIS エラー・リファレンス" にリストされた SQLCODE エラー・メッセージ