パフォーマンス リファレンス
 
このページをシェアする                  
パフォーマンス リファレンス
データベース エンジンのパフォーマンス機能についての検討
Zen データベース エンジンは、多数の最適化を使用します。以下のトピックでは、SQL ステートメントでこれを活用する方法について説明します。この技術的題材は熟練した SQL ユーザー向けです。使用されている用語の定義については、用語を参照してください。
制限の分析
制限の最適化
プッシュダウン フィルター
インデックスの有効な使用法
テンポラリ テーブルのパフォーマンス
行の事前取得
用語
制限の分析
このトピックでは、データベース エンジンが制限を分析し、最適化するために使用する 1 方法について説明します。使用されている技術用語の定義については、用語を参照してください。
変形 CNF 変換
SQL ステートメントの実行中に、データベース エンジンは制限を変形論理積標準形(変形 CNF)に変換しようとします。変形 CNF への変換は、論理式を同一構造に置いて、クエリ処理の最適化のための制限の分析を容易にします。制限を変形 CNF に変換できる場合、データベース エンジンはクエリを順序立てて完全に分析し、利用可能なインデックスを有効に利用できるように最適化します。データベース エンジンが制限を変形 CNF に変換できない場合でも、制限を分析してできる限りの最適化を行います。ただし、この場合データベース エンジンは、既に変形 CNF にある制限や内部的に変形 CNF に変換することができる制限のようには、利用可能なインデックスを有効利用できないことがしばしばあります。
変換できない制限
制限の内容によっては、データベース エンジンが変形 CNF に変換できない制限があります。次の項目のいずれかが真になる場合、制限は変形 CNF に変換されません。
制限にサブクエリが含まれている。
制限に NOT 演算子が含まれている。
制限に動的パラメーターが含まれている(動的パラメーターは SQL ステートメント内の疑問符("?")で、ステートメントが実行されるときに入力を要求される)。
変換が行われない条件
データベース エンジンが制限を変形 CNF に変換できるのにそうしない場合がいくつかあります。変形 CNF 変換後に最適化を適用するよりも元の形式に適用した方が最適化による利益をより多く受けられると判断した場合、データベース エンジンは制限を変形 CNF に変換しないという選択をします。
次の項目のいずれかが真になる場合、制限は変形 CNF に変換されません。
制限が論理和標準形(DNF)になっており、すべての述部が等号(=)、LIKE または IN 比較演算子のみを含む。
たとえば、データベース エンジンは次の制限を変形 CNF に変換しません。
(c1 = 1 AND c2 = 1) OR (c1 = 1 AND c2 = 2) OR (c1 = 2)
制限が次のすべての条件に合致する。
論理和標準形(DNF)の式を含み、制限の残りの部分と AND で結合されている。
指定した DNF 式は、述部のみで、等号(=)、LIKE または IN 比較演算子を含む。
DNF 式内の各論理積で同じ位置にある述部が同一列を参照する。
たとえば、次のを含む制限は変形 CNF に変換されません。
(c1 = 1 AND c2 = 1) OR (c1 = 1 AND c2 = 2)
制限の最適化
ここでは、制限内の式を利用するためにデータベース エンジンが使用する基本技術を詳細に説明します。データベース エンジンが実行する最適化のタイプを単純なものから複雑なものの順に下に示します。
データベース エンジンが使用する最適化技術を完全に理解することは、データベース エンジンでの最適なパフォーマンスを実現するクエリを構築するのに役立ちます。さらに、データベース エンジンがクエリを最適化するためにインデックスをどのように使用するかを理解することにより、一般的な使用で最高のパフォーマンスを提供するインデックスの構築方法を決定することができます。
単純化のために、下の説明ではまず 1 つのテーブルの列を参照する式について述べます。述部で 2 つの異なるテーブルの列を比較する結合条件を使用する最適化は単一テーブルの最適化の次に説明します。
使用されている技術用語の定義については、用語を参照してください。
単一述部の最適化
制限の最適化の最も単純な形式は単一の述部を使用するものです。述部は、次の条件をすべて満たす場合、最適化に使用されます。
述部は AND 演算子で制限の残りの部分と結合されている。
述部の一方のオペランドは先頭セグメントである列の参照で構成され、もう一方のオペランドは列の参照を含まない式で構成されている(つまりリテラル値または直接パラメーターしか含まない)。
比較演算子は <、<=、=、>=、>、LIKE、または IN のいずれかである。
たとえば、最初のセグメントが列 c1 であるインデックスがあるとします。次の述部は最適化に使用されます。
c1 = 1
c1 IN (1,2)
c1 > 1
LIKE 演算子は、2 番目のオペランドがワイルドカード以外の文字で始まる場合のみ最適化されます。たとえば、C2 LIKE 'ABC%' は最適化できますが、C2 LIKE '%ABC' は最適化されません。
閉じた範囲の最適化
閉じた範囲は、単一述部の最適化の条件をすべて満たす場合、最適化に使用されます。
たとえば、最初のセグメントが列 c1 であるインデックスがあるとします。次の閉じた範囲は最適化に使用されます。
c1 >= 1 AND c1 < 10
変形論理和の最適化
変形論理和は、次の条件にすべて合致する場合、最適化に使用されます。
制限の残りの部分と AND 演算子で結合されている。
論理和内のそれぞれの述部および閉じた範囲単一述部の最適化および閉じた範囲の最適化の要件を満たしている。
述部または閉じた範囲がそれぞれもう一方と同じ列を参照している。
たとえば、最初のセグメントが列 c1 であるインデックスがあるとします。次の変形論理和は最適化に使用されます。
c1 = 1 OR (c1 > 5 AND c1 < 10) OR c1 > 20
次の変形論理和は、すべての述部と閉じた範囲内で同一列が参照されていないため、このタイプの最適化には使用されません。
c1 = 1 OR (c1 > 5 AND c1 < 10) OR c2 = 1
論理積の最適化
論理積は、次の条件にすべて合致する場合、最適化に使用されます。
制限の残りの部分と AND 演算子で結合されている。
論理積内のそれぞれの述部は、単一述部の最適化の要件を満たしている。
それぞれの述部はインデックスの先頭セグメントで最適化を行っており、セグメントごとに 1 つの述部のみを使用している(つまり、同じ先頭セグメントのセットを使用する 2 つの異なる述部はない)。
最適化に使用される最後のセグメントを参照する述部以外のすべての述部は、等号(=)比較演算子を使用している。
たとえば、最初の 3 つのセグメントとして列 c1、c2、c3 をこの順序で持つインデックスがあるとします。次の論理積の配置は最適化に使用されます。
c1 = 1 AND c2 = 1 AND c3 = 1
c1 = 1 AND c2 = 1 AND c3 >= 1
c1 = 1 AND c2 > 1
述部の順序は関係ありません。たとえば、次の論理積は最適化に使用されます。
c2 = 1 AND c3 = 1 AND c1 = 1
次の論理積は、インデックスの 2 番目のセグメントが飛ばされているため(列 c2 への参照がない)、最適化には使用されません。
c1 = 1 AND c3 = 1
この場合、単一の述部 c1 = 1 は最適化に使用されます。
論理和標準形の最適化
論理和標準形(DNF)の式は、次の条件をすべて満たす場合、最適化に使用されます。
制限の残りの部分と AND 演算子で結合されている。
式のそれぞれの論理積は、論理積の最適化の要件を満たし、さらにすべての述部が等号(=)比較演算子を含む必要がある。
すべての論理積は、最適化に、同じインデックスと同じ数のセグメントを使用する必要がある。
データベース エンジンは、元から DNF にあった制限を変形 CNF に変換しません。これは DNF 上で最適化されるためです。
たとえば、最初の 3 つのセグメントとして列 c1、c2、c3 をこの順序で持つインデックスがあるとします。DNF の次の式は最適化に使用されます。
(c1 = 1 AND c2 = 1 AND c3 = 1) OR (c1 = 1 AND c2 = 1 AND c3 = 2) OR (c1 = 2 AND c2 = 2 AND c3 = 2)
DNF の次の式は、両方の論理積が同数のセグメントを参照していないため、最適化に使用されません。
(c1 = 1 AND c2 = 1 AND c3 = 1) OR (c1 = 1 AND c2 = 2)
変形論理積標準形の最適化
変形論理積標準形(変形 CNF)の式は、次の条件をすべて満たす場合、最適化に使用されます。
制限の残りの部分と AND 演算子で結合されている。
それぞれの変形論理和変形論理和の最適化の要件を満たしている。ただし、それぞれの変形論理和は、先頭セグメントを共に構成するインデックス セグメントの別のセグメントを参照している必要がある(つまり、すべての論理和をまとめると、どのセグメントも抜けていない)
すべての変形論理和は、最後のセグメントを参照するものを除き、等号(=)比較演算子を使用する述部を少なくとも 1 つ含む。
変形 CNF 最適化は DNF 最適化と似ていますが、DNF 最適化ではサポートされない、異なる比較演算子を含む述部の組み合わせを使用することができます。
たとえば、最初の 3 つのセグメントとして列 c1、c2、c3 をこの順序で持つインデックスがあるとします。変形 CNF の次の式は最適化に使用されます。
(c1 = 1 OR c1 = 2) AND (c2 = 1 OR (c2 > 2 AND c2 < 5)) AND (c3 > 1)
変形 DNF 内の等号式に注目すると、データベース エンジンがこの式を最適化に使用する方法を簡単に理解できます。
(c1 = 1 AND c2 = 1 AND c3 > 1) OR (c1 = 1 AND (c2 > 2 AND c2 < 5) AND c3 > 1) OR (c1 = 2 AND c2 = 1 AND c3 > 1) OR (c1 = 2 AND (c2 > 2 AND c2 < 5) AND c3 > 1)
変形 CNF 最適化で開いた範囲を閉じる
2 つの変形論理和は、次の条件を満たす場合、結合されて 1 つまたは複数の閉じた範囲を形成します。
変形論理和は変形論理和の最適化の要件を満たしている。
両方の変形論理和が同一インデックスの同一セグメントを使用している。
どちらの変形論理和も開いた範囲を含んでおり、それらを結合して 1 つまたは複数の閉じた範囲を形成できる。
たとえば、最初のセグメントが列 c1 であるインデックスがあるとします。変形 CNF の次の式は最適化に使用されます。
(c1 = 1 OR c1 > 2) AND (c1 < 5 OR c1 = 10)
単純な変形論理和である等号式に注目すると、データベース エンジンがこの式を最適化に使用する方法が簡単に理解できます。
c1 = 1 OR (c1 > 2 AND c1 < 5) OR c1 = 10
単一結合条件の最適化
2 つのテーブルにかかわる最適化の最も単純な形式は、単一の結合条件を利用するものです。単一の結合条件の最適化は単一述部の最適化に似ています。結合条件は、単一述部の最適化の条件をすべて満たす場合、最適化に使用されます。結合条件を使用して最適化されるテーブルは、結合条件内で参照されるほかのテーブルの後で処理されます。結合条件を使用して最適化されるテーブルは、結合条件内で参照されるほかのテーブルの行から取得した最適化値を使用します。
たとえば、テーブル t1 に最初のセグメントが列 c1 であるインデックスがあるとします。次の結合条件は最適化に使用されます。
t1.c1 = t2.c2
t1.c1 > t2.c2
最適化中、行はテーブル t2 から取得されます。この行から、列 c2 の値を使用して、結合条件に従ってテーブル t1 を最適化します。
t1.c1 のインデックスの代わりに t2.c2 のインデックスがある場合には、t1.c1=t2.c2 によってテーブル t2 を最適化できます。この場合、テーブル t1 が最初に処理され、t1.c1 の値を基に、結合条件に従ってテーブル t2 が最適化されます。
t1.c1 のインデックスだけでなく t2.c2 のインデックスも存在する場合には、データベース エンジンのクエリ オプティマイザーは両方のテーブルのサイズに加え、2 つのインデックスの特性も調べて、全体で最高のクエリ パフォーマンスを提供するテーブルを選択します。
結合条件を持つ論理積の最適化
結合条件とほかの述部の混成である論理積は、次の条件をすべて満たす場合、最適化に使用されます。
すべての結合条件が同じ 2 つのテーブルの列を比較する。
論理積は、2 つのテーブルのいずれかの通常の論理積の最適化の要件を満たしている。
論理積を使用して最適化されるテーブルは、結合条件内で参照されるほかのテーブルの後で処理されます。
たとえば、テーブル t1 に最初の 3 つのセグメントとして列 c1、c2、c3 をこの順序で持つインデックスがあるとします。次の論理積は最適化に使用されます。
t1.c1 = t2.c1 AND t1.c2 = t2.c2 AND t1.c3 = t2.c3
t1.c1 = t2.c1 AND t1.c2 > t2.c2
t1.c1 = t2.c1 AND t1.c2 = 1
t1.c1 = 1 AND t1.c2 = t2.c2
結合条件を持つ変形論理積標準形の最適化
結合条件を含む変形論理積標準形(変形 CNF)は、次の条件をすべて満たす場合、最適化に使用されます。
変形論理積標準形の最適化の条件を満たしている。
さらに、使用されている先頭セグメントの最後の部分で最適化する論理和以外のすべての論理和は、単一の結合条件または単一の述部のみを含み、少なくともその中の 1 つは単一結合条件である必要がある。
たとえば、テーブル t1 に最初の 3 つのセグメントとして列 c1、c2、c3 をこの順序で持つインデックスがあるとします。変形 CNF の次の式は最適化に使用されます。
(t1.c1 = t2.c1) AND (t1.c2 = t2.c2 OR
(t1.c2 > 2 AND t1.c2 < 5))
 
(t1.c1 = 1) AND (t1.c2 = t2.c2) AND
(t1.c3 > 2 AND t1.c3 < 5)
変形 CNF 最適化で結合条件の開いた範囲を閉じる
このタイプの最適化は、閉じられる範囲が結合条件であることを除けば、まさに変形 CNF 最適化で開いた範囲を閉じるとよく似ています。
たとえば、テーブル t1 に最初の 2 つのセグメントとして列 c1、c2 をこの順序で持つインデックスがあるとします。変形 CNF の次の式は最適化に使用されます。
(t1.c1 > t2.c1) AND (t1.c1 < t2.c2 OR t1.c1 = 10)
 
(t1.c1 = t2.c1) AND (t1.c2 > t2.c2) AND (t1.c2 < 10 OR t1.c2 = 100)
複数インデックスの変形論理和の最適化
変形論理和は、次の条件にすべて合致する場合、複数のインデックスを使用して最適化に使用されます。
制限の残りの部分と AND 演算子で結合されている。
論理和内のそれぞれの述部および閉じた範囲は、単一述部の最適化または閉じた範囲の最適化の要件をそれぞれ満たしている。
それぞれの述部または閉じた範囲は、インデックスの最初のセグメントである列を参照する。すべての述部と閉じた範囲が同一列を参照する場合、このシナリオは単に、前述の変形論理和の最適化のとおりとなる。
たとえば、最初のセグメントが列 c1であるインデックスと、最初のセグメントが列 c2 であるもう 1 つのインデックスがあるとします。次の変形論理和は最適化に使用されます。
c1 = 1 OR (c1 > 5 AND c1 < 10) OR c2 = 1
プッシュダウン フィルター
プッシュダウン フィルターは厳密には内部的な最適化技術です。高速なフィルター処理能力を利用することにより、データベース エンジンは、制限の特性に応じて結果セットから拒否する特定の行を効率的に識別することができます。結果セットから行を排斥してから結果セットを返すため、データベース エンジンが分析する必要のある行数が減り、プッシュダウン フィルターを使用しない場合よりも速く処理を完了します。
データベース エンジンは、次の条件が満たされる場合、式または式の組み合わせをプッシュダウン フィルターとして使用できます。
述部は、制限の残りの部分と AND 演算子で結合されている場合、プッシュダウン フィルターで使用できる。
述部は、1 つのオペランドが列参照から成り、ほかのオペランドがリテラル値または動的パラメーター("?")から成る場合、プッシュダウン フィルターで使用できる。また、参照される列のデータ型は、bit、float、double、real、longvarchar、longvarbinary または binary のいずれでもない必要がある。
述部は、比較演算子が <、<=、=、>=、>、または <> のいずれかである場合、プッシュダウン フィルターで使用できる。
論理和は、制限の残りの部分と AND 演算子で結合されており、論理和内のすべての述部がプッシュダウン フィルターで使用される述部の要件を満たしている(ただし、述部が制限の残りの部分と AND 演算子で結合されている必要があるという要件を除く)場合、プッシュダウン フィルターで使用できる。プッシュダウン フィルターに含めることができる論理和は 1 つだけである。
プッシュダウン フィルターは単一の論理和およびプッシュダウン フィルターで使用される述部の要件を満たす述部を組み合わせることができる。
使用されている技術用語の定義については、用語を参照してください。
インデックスの有効な使用法
インデックスは、制限以外の DISTINCT や ORDER BY 句などのクエリ特性を最適化することができます。
使用されている技術用語の定義については、用語を参照してください。
集計関数の DISTINCT
DISTINCT キーワード付きの集計関数から成る選択リストが指定されているクエリでは、インデックスの使用によって取得する行数を減らすことができます。このタイプの最適化の対象となるには、DISTINCT キーワードが作用する式は単一の列参照で構成されている必要があります。さらに、その列はインデックスの先頭セグメントである必要があります。
たとえば、テーブル t1 に最初のセグメントが列 c1 であるインデックスがあるとします。インデックスを使用すると、列 c1 の値が重複している行の取得を回避することができます。
SELECT COUNT(DISTINCT c1) FROM t1 WHERE c2 = 1
選択リストに先立つ DISTINCT
選択リストの前に DISTINCT キーワードが指定されているクエリでは、インデックスの使用によって取得する行数を減らすことができます。このタイプの最適化の対象となるには、選択リストは列参照のみから成り(算術式やスカラー関数のような複合式を含まない)、参照列は単一インデックスの先頭セグメントである必要があります。
たとえば、テーブル t1 に最初の 3 つのセグメントとして列 c1、c2、c3 を任意の順序で持つインデックスがあるとします。インデックスを使用すると、選択リストの各項目の値が重複している行の取得を回避することができます。
SELECT DISTINCT c1, c2, c3 FROM t1 WHERE c2 = 1
インデックスのセグメント順序
ORDER BY 句で最適化のためにインデックスが使用されるかどうかは、インデックスのセグメントとして列がどのような順序で現れるかによります。具体的には、このタイプの最適化の対象となるには、ORDER BY 句内の列はインデックスの先頭セグメントである必要があり、インデックス内でセグメントとして現れる順序と同じ順序で ORDER BY 句に現れる必要があります。
これとは対照的に、選択リストや GROUP BY 句の場合は、インデックスの先頭セグメントの列で構成されてさえいれば、選択リストの前にある DISTINCT または GROUP BY 句の最適化にインデックスを使用できます。このステートメントは、インデックス内のセグメントとして列が現れる順序にかかわらず真です。
たとえば、テーブル t1 に最初の 3 つのセグメントとして列 c1、c2、c3 を任意の順序で持つインデックスがあるとします。次のクエリでは、DISTINCT で最適化を行うためにインデックスが使用されます。
SELECT DISTINCT c1, c2, c3 FROM t1
SELECT DISTINCT c2, c3, c1 FROM t1 WHERE c3 > 1
次のクエリでは、GROUP BY で最適化を行うためにインデックスが使用されます。
SELECT c1, c2, c3, count(*) FROM t1 GROUP BY c2, c1, c3
SELECT c2, c3, c1, count(*) FROM t1 GROUP BY c3, c2, c1
ただし、ORDER BY での最適化に使用されるインデックスは、c2、c1、c3 の順序である必要があります。
SELECT c1, c2, c3 FROM t1 ORDER BY c2, c1, c3
セグメントの昇順属性
ORDER BY 句で最適化にインデックスが使用されるかどうかは、いくつかの条件によって決まります。
具体的には、インデックスは次の条件をすべて満たす場合、最適化に使用されます。
ORDER BY 句で列名に続いて DESC キーワードがある。
対応するインデックス セグメントが降順で定義されている。
指定した列がヌル可能列ではない。
さらに、インデックスは次の逆の条件をすべて満たす場合、最適化に使用されます(ヌル可能列は昇順の ORDER BY では使用できます)。
ORDER BY ステートメントで列名の後に ASC キーワードまたは ASC でも DESC でもないものが続く。
対応するインデックス セグメントが昇順で定義されている。
同様に、関連するすべてのセグメントの昇順または降順属性が ORDER BY 句で指定された ASC または DESC キーワードと完全に反する場合、ORDER BY の最適化にインデックスが使用されます。さらに、降順に定義されたセグメントは、関連する列がヌル可能列でない場合にのみ使用されます。
インデックスは、いずれかのセグメントの属性が昇順であるか降順であるかに関係なく、制限の最適化、DISTINCT の最適化または GROUP BY 句の最適化に使用されます。
たとえば、テーブル t1 に最初の 2 つのセグメントとして列 c1、c2 をこの順序で持つインデックスがあり、セグメントは 2 つとも昇順であるとします。このインデックスは、次のクエリで最適化を行うために使用することができます。
SELECT c1, c2, c3 FROM t1 ORDER BY c1, c2
SELECT c1, c2, c3 FROM t1 ORDER BY c1 DESC, c2 DESC
SELECT DISTINCT c1, c2 FROM t1
SELECT DISTINCT c2, c1 FROM t1
SELECT * FROM t1 WHERE c1 = 1
テーブル t1 に最初の 2 つのセグメントとして列 c1、c2 をこの順序で持つインデックスがあり、c1 のセグメントは昇順、c2 のセグメントは降順に定義されているとします。また c2 はヌル可能列であるとします。2 番目のセグメントは降順かつヌル可能列であるため、ORDER BY の最適化には使用できません。このインデックスは、次のクエリで最適化を行うために使用することができます
SELECT c1, c2, c3 FROM t1 ORDER BY c1
SELECT c1, c2, c3 FROM t1 ORDER BY c1 DESC
SELECT DISTINCT c1, c2 FROM t1
SELECT DISTINCT c2, c1 FROM t1
SELECT * FROM t1 WHERE c1 = 1
c2 列がヌル可能列でない場合、インデックスは次のクエリで最適化を行うために使用することができます。
SELECT c1, c2, c3 FROM t1 ORDER BY c1, c2 DESC
SELECT c1, c2, c3 FROM t1 ORDER BY c1 DESC, c2
検索更新の最適化
インデックスの先頭セグメントを更新するとき、検索のための WHERE 句で同じインデックスを使うことによって、検索の最適化を利用することができます。データベース エンジンは、UPDATE 用のセッション(クライアント ID)と、もう 1 つ検索用のセッションを使用します。
次のステートメントは、検索の最適化によって利益を得られます。
CREATE TABLE t1 (c1 INT)
CREATE INDEX t1_c1 ON t1(c1)
INSERT INTO t1 VALUES(1)
INSERT INTO t1 VALUES(1)
INSERT INTO t1 VALUES(9)
INSERT INTO t1 VALUES(10)
INSERT INTO t1 VALUES(10)
UPDATE t1 SET c1 = 2 WHERE c1 = 10
UPDATE t1 SET c1 = c1 + 1 WHERE c1 >= 1
テンポラリ テーブルのパフォーマンス
パフォーマンスの改善は、このリリースでテンポラリ ソート テーブルの実装に対しても行われました。クエリを処理するには、データベース エンジンは内部的な使用目的でテンポラリ テーブルを生成する必要があります。これらのクエリの多くに対するパフォーマンスが改善されました。
一般的に、次の条件のいずれかが真の場合、データベース エンジンは少なくとも 1 つのテンポラリ テーブルを生成してクエリを処理します。
選択リストの前に DISTINCT キーワードがあり、選択リストの項目がインデックスの先頭セグメントの列ではない。
たとえば次の場合、列 c1 および c2 を先頭セグメントとするインデックスが存在しなければ、クエリを処理するためにテンポラリ テーブルが生成されます。
SELECT DISTINCT c1, c2 FROM t1
GROUP BY 句が使用されており、GROUP BY 句内の項目がインデックスの先頭セグメントの列ではない。
たとえば次の場合、列 c1 および c2 を先頭セグメントとするインデックスが存在しなければ、クエリを処理するためにテンポラリ テーブルが生成されます。
SELECT c1, c2, COUNT(*) FROM t1 GROUP BY c1, c2
静的カーソルが使用されている。
たとえば、アプリケーションが結果セットを作成する前に SQL_CURSOR_TYPE オプションと SQL_CURSOR_STATIC 値を指定して ODBC API の SQLSetStmtOption を呼び出す場合、テンポラリ テーブルが生成されます。
結果セットにブックマークが含まれる。
たとえば、結果セットを生成する前に SQL_USE_BOOKMARKS オプションと SQL_UB_ON 値を指定して ODBC API の SQLSetStmtOption を呼び出す場合です。
クエリは、IN または =ANY キーワードの右側に非相関サブクエリを含む。
たとえば、次のような例です。
SELECT c1 FROM t1 WHERE c2 IN (SELECT c2 FROM t2)
行の事前取得
特定の状況下で、SELECT ステートメントを実行した場合、このリリースのデータベース エンジンはクライアントに対し、結果の行セットの最初の 2 行をあらかじめ取得しようとします。この事前取得により、ゼロ行または 1 行の結果セットからデータを取得するパフォーマンスが著しく改善されます。
結果セットが複数の行から成り、最初のデータ取得操作で要求される行が結果セットの最初の行でない場合、たとえば最後の行である場合には、行の事前取得は著しく時間を無駄にします。このため、事前取得がもたらす利点が意味を成さないケースを回避する一方、利点をもたらすケースでのパフォーマンスの改善を目指すため、事前取得は最大 2 行に制限されています。
事前取得は、クライアント DSN 用の詳細な接続属性で[配列フェッチ]が有効になっている場合にのみ行われます(『ODBC Guide』の詳細な接続属性を参照してください)。配列フェッチは事前取得と似ていますが、配列フェッチは最初の明示的なデータ取得操作が実行されるまでは行われない点が異なります。この違いは、最初の明示的なデータ取得操作により、データベース エンジンが残りの結果セットを取得する方法を推定できるだけの情報が提供されるためです。たとえば、最初のデータ取得操作が ODBC API の SQLFetch 呼び出しであった場合、これにより、データベース エンジンは結果セット全体を一度に 1 レコードずつ前方へ取得していくことが確実に推定できます。このように推定できるのは、ODBC の仕様によると、SQLFetch を使用した場合は残りの結果セットも同様に SQLFetch で取得されることが必要となるためです。一方、SQLExtendedFetch が呼び出され、行セットのサイズが 1 より大きい場合には、クライアントは開発者が最適な行セット サイズを指定したものと推定し、配列フェッチによってその設定を無効にしません。
事前取得は、次の条件のすべてが満たされた場合に起こります。
配列フェッチが有効である。
結果セットは大きな可変長データを含まない。たとえば、選択リストに LONGVARCHAR または LONGVARBINARY 型の列を含まない。
結果セットにブックマークが含まれない。
たとえば、結果セットの生成前に SQL_USE_BOOKMARKS オプションおよび SQL_UB_ON 値を指定して ODBC API の SQLSetStmtOption が呼び出された場合、事前取得は行われません。
読み取り専用の並行カーソルが使用されている。
たとえば、結果セットの生成前に、SQL_CONCURRENCY オプションおよび SQL_CONCUR_READ_ONLY 以外の値を指定して ODBC API の SQLSetStmtOption が呼び出された場合、事前取得は行われません。デフォルトで、並行カーソルは読み取り専用です。
用語
このトピックでは、ここで述べた複雑な技術的題材についての理解を助けるための定義や例を示します。
インデックス
インデックスは、テーブル内の 1 つ以上の列に関連付けられた構造で、データベース エンジンが効率的に検索と並べ替えを実行できるようにするものです。インデックスを利用すると、データベース エンジンはテーブル内のすべての行を調べる代わりに検索条件を満たす特定の行のみを読み取ることができ、検索パフォーマンスを向上させることができます。また、インデックスを利用すれば、行を取得した後で効率の悪い技術を使って並べ替えしなくても、SQL クエリで指定した順序で行を取得できます。
結合条件
結合条件は <、<=、=、>=、> の比較演算子を使用して、あるテーブルの列を別のテーブルの列と比較する述部です。
たとえば、次の述部は結合条件です。
t1.c1 = t2.c1
t1.c1 > t2.c2
式は、制限で使用できるブール代数で構成されます。少なくとも 1 つ以上の完全な述部を含む制限全体または制限の一部が式です。
集計関数
集計関数は、クエリの SELECT または HAVING 句の値のグループを使用して単一の値を生成します。集計関数には、COUNT、AVG、SUM、STDEV、MAX、MIN、および DISTINCT があります。
述部
述部は、AND または OR の論理演算子を含まない論理式です(BETWEEN は除く)。
たとえば、次の式は述部です。
(c1 = 1)
(c1 LIKE 'abc')
(c1 BETWEEN 1 AND 2)
次の例は述部ではありません
(c1 > 1 AND c1 < 5)
(c1 = 1 OR c1 = 2)
制限
制限は SQL クエリの WHERE 句全体です。
先頭セグメント
インデックス セグメントのグループが、インデックスの最初の n 列(n はインデックスの総セグメント数以下の任意の数値)で構成されている場合、このグループは先頭セグメントです。たとえば、インデックスが列 c1、c2、c4 をセグメントとして定義されている場合、c1 は先頭セグメントと呼ばれます。また、c1 と c2 を合わせても先頭セグメント、3 つすべて合わせても先頭セグメントと言いますが、c2 単独では先頭セグメントと言いません。これは、c2 の前にあるセグメント c1 が除外されているためです。列 c1 と c4 を合わせても先頭セグメントとは言いません。c4 の前にある c2 が除外されているためです。
閉じた範囲
閉じた範囲とは、AND 演算子で結合された 1 組の開いた範囲です。開いた範囲は両方とも同じ列を参照し、一方は < または <= 比較演算子を含み、もう一方は >= または > 演算子を含む必要があります。BETWEEN 句も閉じた範囲を定義します。
たとえば、次の式は閉じた範囲です。
c1 > 1 AND c1 <= 10
c1 BETWEEN 1 AND 10
開いた範囲
開いた範囲は、<、<=、>=、または > のいずれかの比較演算子を持つ述部です。さらに、述部のオペランドの 1 つは単一の列で構成され、もう一方のオペランドはほかのテーブルの単一の列またはリテラルで構成されている必要があります。
たとえば、次の式は開いた範囲です。
c1 > 1
c1 <= 10
t1.c1 > t2.c1
変形論理積標準形(変形 CNF)
変形論理積標準形内の論理積標準形(CNF)内の式と似ていますが、各論理和閉じた範囲に加えて述部を含む点が異なります。
たとえば、次の式は変形 CNF です。
c1 = 2 AND c2 < 5
(c1 = 2 OR (c1 > 4 AND c1 < 6) OR c1 = 10) AND (c2 = 1 OR c3 = 'efg')
変形論理和
変形論理和は論理和と似ていますが、閉じた範囲に加えて述部を含む点が異なります。
たとえば、次の式は変形論理和です。
c1 = 2 OR (c1 > 4 AND c1 < 5)
(c1 = 2 OR (c1 > 4 AND c1 < 5)) OR c2 = 'abc'
論理積
論理積は、2 つ以上の述部が AND 演算子で結合された式です。たとえば、次の制限は論理積です。
c1=2 AND c2<5
c1>2 AND c1<5 AND c2= 'abc'
論理積標準形(CNF)
あるが AND 演算子で結合された 2 つ以上の論理和を含む場合、それは論理積標準形です。たとえば、次の式は CNF です。
c1 = 2 AND c2 < 5
(c1 = 2 OR c1 = 5) AND (c2 < 5 OR c2 > 20) AND (c3 = 'abc' OR c3 = 'efg')
論理和
論理和は、2 つ以上の述部が OR 演算子で結合されたです。たとえば、次の式は論理和です。
c1 = 2 OR c2 = 5
c1 = 2 OR c1 > 5 OR c2 = 'abc'
論理和標準形(DNF)
あるが OR 演算子で結合された 2 つ以上の論理積を含む場合、それは論理和標準形です。たとえば、次の式は DNF です。
c1 = 2 OR c2 < 5
(c1 = 2 AND c2 = 5) OR (c2 > 5 AND c2 < 10) OR c3 = 'abc'