一般的なデータベースの本を読むと、

インデックスの中にNULLは含まれず、NULL述語を指定した検索はテーブルスキャンが実行されるそうです。
しかし、Microsoft SQL Server 2000やMySQL(InnoDB)で実際に検証したところ、
インデックスシークが行われているようでした。

下記の点について教えてください。

1. このような本の記述が正しいのか、
2. また、Oracleについてはそういえるのか、
3. そして、なぜそのような実装になっているか

回答の条件
  • 1人10回まで
  • 登録:
  • 終了:2007/01/22 17:22:48
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答3件)

id:ohmix1 No.1

回答回数235ベストアンサー獲得回数14

ポイント27pt

中途半端な回答で申し訳ありませんが...


>1. このような本の記述が正しいのか、


たぶん、概念的には正しいものと思われます。

なぜなら、NULLは\\\"値\\\"ではなく\\\"不定\\\"だから。


根本的には、

WHERE ID = NULL でなく、

WHERE ID IS NULL なのが理由になると思われ....説明できません。orz


詳しくは、以下の「NULLにまつわる諸問題」あたり。

http://www.geocities.jp/mickindex/database/idx_database.html




>2. また、Oracleについてはそういえるのか、


http://otn.oracle.co.jp/document/products/oracle9i/920/general.h...


Oracle9i データベース・パフォーマンス・チューニング・ガイドおよびリファレンス リリース2(9.2)


によると以下のような場合は全表スキャンになるようです。


>全表スキャンは、このリストの中で最も順位の低いアクセス・パスです。つまり、全表ス

>キャンの方が高速で実行できるとしても、索引を使用するアクセス・パスが使用可能であれ

>ば、RBO は常に索引を使用するアクセス・パスを選択します。

>次の条件は、索引アクセス・パスを使用不可にします。


... 中略 ...


> 列IS NULL

> 列IS NOT NULL

> 列NOT IN

> 列 != expr

> 列LIKE \\\'%pattern\\\'

>列に索引が作成されているかどうかは関係ありません。




>3. そして、なぜそのような実装になっているか


なぜ、索引シークが可能なDBがあるかは、NULLを値のようにあつかうような実装をしているのではないかと...


id:witt

データベースの本は中立を装っていても、どうしてもOracleの実装を前提に書かれているので本質問をさせていただきました。

ohmix1さんの次のように回答されたように、

>>3. そして、なぜそのような実装になっているか

>なぜ、索引シークが可能なDBがあるかは、NULLを値のようにあつかうような実装をしているのではないかと...

このような実装が素直で納得ができるのですが、対して、Oracleの実装が素直に感じられず、なぜこうする理由があるのか知りたいです。

2007/01/19 14:31:33
id:b-wind No.2

回答回数3344ベストアンサー獲得回数440

ポイント27pt

1.正しい

NULL は値ではなく不定値であり、SQLにおいて3値論理を実現するものだからです。

http://codezine.jp/a/article/aid/532.aspx

つまり特定の値ではないので

NULL = NULL

は偽です。

インデックスは特定の値からレコードを導き出すものなので本来は作成しようがありません。

たとえばインデックスの作成に良く使われる B-Tree では構築と検索処理に値の大小が深く関係しています。

http://www.mars.dti.ne.jp/~torao/program/structure/btree.html

NULL の大小比較は不可能なのでインデックスに入れられません。

理論上は、ですが。


2.YES

http://www.atmarkit.co.jp/fdb/rensai/orasql07/orasql07_1.html

少々古い記事ですが、IS NULL での EXPLAIN の結果が載っています。


3.すいませんがわかりません。

確かに MySQL では IS NULL はインデックス検索可能なようでドキュメントにも記載があります。

http://dev.mysql.com/doc/refman/4.1/ja/is-null-optimisation.html

ただ、これはあくまで特定の実装における現象であり、RDBMS 全般に適用するのは不適切だと考えます。(あくまで理論として)

実用上はインデックスが活用される機会が増えるので、便利ではありますが。

id:witt

>NULL = NULL

>は偽です。

3値論理なので、unknownですよね?

さて、ご回答を受けて熟考した結果、私の質問におかしなところが

あると思いました。

>インデックスの中にNULLは含まれず、NULL述語を指定した検索はテーブルスキャンが実行されるそうです。

前半は理論上の話で、後半は実装上の話。

違うレベルの話がごちゃまぜになっていて不適切でした。

そして、前半は正しく、後半は実装による、というのがご回答を受けての私の結論です。

MySQLのドキュメントについては非常にうなづけました。

確かな情報ありがとうございます。

実用上、そう最適化するのが適当だろうと思います。

自分の考え方に自信が持てました。

2007/01/20 13:10:32
id:b-wind No.3

回答回数3344ベストアンサー獲得回数440

ポイント26pt

3についての考察。

あまり SQL Server については詳しくないのですが。


http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=632765&...

Index を使用する場合でも Index Seek と Index Scan の2種類あるようです。

ただ、このリンク先の回答では「ペナルティがある」との発言から Seek と Scan を逆に書いてしまっているように受け取れます。


これらの違いについては以下に説明が有りました。

http://oshiete1.goo.ne.jp/kotaeru.php3?q=844899

http://www.sqlpassj.org/conf/session/pdf/A3.pdf


理屈から言えば IS NULL の検索は Index Scan になるはずだと思いました。

id:witt

この件については、動作検証したところ、Index Seekになります。

リンク先の「ペナルティがある」との発言が疑問です。

Index Seekが可能な検索ならば、Index Scanにする意味がないと思いました。

2007/01/20 13:18:26
  • id:b-wind
    >>NULL = NULL
    >>は偽です。
    >3値論理なので、unknownですよね?
    失礼。確かにそうですね。


    ちなみに試してはいませんが、もう一つのOSSDBの雄 PostgreSQL では IS NULL でのインデックススキャンは出来ないようです。
    http://www.postgresql.jp/document/pg821doc/html/indexes-types.html
    > しかし、IS NULLは=と異なり、インデックスではできません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません