2017-11-24 1 views
0

2つの可能な値(YとN)を持つ列にインデックスを作成しましたが、データ型は両方の値で同じです。2つのタイプの値を持つ列にのみインデックスを作成すると効率的です

カラム名がインジケータであるとします。 私は、SQLの開発者にこのクエリのプランを説明使用する場合、完全なテーブルがないインデックス・スキャンをスキャン使用している、のような

SELECT INDICATOR 
FROM TEMP_TABLE 
ORDER BY INDICATOR 

をselect文を書きました。

なぜインデックステーブルスキャンを使用していないのですか。

+0

これらは2つの値です。彼らは同じタイプを持っています。2つのタイプの値はありません。 – mathguy

+0

値は同じデータ型ですが、2つの異なる値YとNがあります。 –

+0

テーブルには何行ありますか? –

答えて

0

索引のない表のレコードを検索するには、DBMSは一致するレコードをすべて読み取る必要があります。索引では、DBMSは一致するものを見つけるために一連の連続したレコードを読み取るだけで、テーブル内の対応するレコードを見つける必要があります。したがって、DBMSが索引を使用する場合、追加のステップがあります。

大まかには、テーブルからレコードの5%以上を読み取っている場合、フルテーブルスキャンはインデックス付き検索よりも高速になります。

しかし、データの配布も重要です。データの99%が「Y」である場合を考えてみましょう。インデックスを使用して 'Y'でレコードを解決すると、非常に非効率になります(私の経験則の逆数を適用すると、フルテーブルスキャンの20倍の時間がかかります)。 OTOHでは、索引を使用してレコードを 'N'で検索すると、全表スキャンより5倍効率が向上します。

これは、より複雑な索引属性にヒストグラムを使用する理由です。

Oracleには、バインド・ピーキングと呼ばれる機能もあります。これは、配布に関する問題を利用して、検索対象の述語に基づいて最も効率的な問合せを選択します。クエリのパターンがデータのパターンと一致したときに何が起こるか考えてみてください。キャッシュされたプランは、最初に処理されるクエリのバージョンによって異なります。

短いバージョン:カーディナリティーが非常に低い(一連の)属性にインデックスを使用しないでください。

+0

私は同意しません。あなたの例のように、データの99%が「Y」であるとします。 'N'フラグを持つ行を選択するクエリが多数ある場合(または頻繁に実行されるクエリがほとんどない場合)、インデックスは完璧な意味を持ちます。 – mathguy

+0

また、私はOPが索引付けされた列のみを読み取っていることに気付きました。この場合、データベースは索引のみを読み取る必要があります。基本表からANYTHINGを読み取る必要はありません。だから私はOPの特定の質問には当てはまらないので、私は上記のコメントで指摘したものを除いて自分の答えを削除した。 – mathguy

0

索引 - 少なくともOracleでは、私は他のデータベースについてはわかりません - 基礎となる列からNULLを保管しません。列からすべての値を読み取るように要求しているので、索引付き列を読んでいるにもかかわらず、基数表から索引を読み取る必要があります(カーディナリティの見積もりやその他の要素に関係なく索引を使用する必要がある場合) 。

今や、あなたの列にはNULLがないと言います。本当にあなたが言ったことを意味し、すべての行に 'Y'または 'N'があり、NULLがありません。

これは問題ありませんが、データを取得して検査した後にのみ有効です。むしろ、期待どおりに索引を使用したい場合、Oracleはデータを最初に見ることなくその列にNULLがないことを知る必要があります。つまり、テーブルにはCONSTRAINTが必要です。実際には、列がNOT NULLことになっている場合は、

ALTER TABLE TEMP_TABLE MODIFY (INDICATOR NOT NULL); 

また、

SELECT INDICATOR 
FROM TEMP_TABLE 
WHERE INDICATOR IS NOT NULL -- ADDED! 
ORDER BY INDICATOR 

は(!それを試してみてください)インデックスを使用しますすることができます。しかし、もし列がNOT NULLでなければならないなら、なぜそれを制約で明示的にしてはいけませんか?

関連する問題