該当データが存在しないときに、全件検索を回避するには?

このQ&Aのポイント
  • Oracle 10gで特定のデータが存在しない場合に、全件検索を回避する方法を知りたいです。
  • データベーステーブルにおいて、インデックスを使わないで特定のデータの存在を確認する方法を教えてください。
  • データベーステーブルのインデックスがない状態で、特定のデータの存在を効率的に確認する方法を教えてください。
回答を見る
  • ベストアンサー

該当データが存在しないときに、全件検索を回避するには?

たとえば、以下のA01KINGAKUテーブルがあったとして KAISHA CHAR(2) (主キー) KINGAKU NUMBER(15) このテーブルに1万件のデータが入っていて 各レコードのKAISHA項目は、全て 'A1' だったとしたとき Select * from A01KINGAKU where KAISHA = 'A2' としたときに、 インデックスをみれば、A2が存在しないというのは すぐにわかりそうなものですが、 Oracle 10gで、これをしたら、全件検索されてしまいました。 (統計情報は直前に取得済みです) たぶん、インデックスの値に散らばりがないので インデックスを使わないという判断になったのだと思いますが インデックスを強要する術はないでしょうか? /*+index(A01KINGAKU インデックス名)+*/ とすればよいのでしょうが こうしたことを多数のテーブルについてやりたく いちいちインデックス名を調べるのがわずらわしく インデックス名がいらないヒントの方法あるいは ヒントとはまったく違った方法を探しています。 (そもそもそんなもの主キーにするなとか、質問の意図が読めないというご意見もあるかと思います。 元は、ALLKINGAKUテーブルという複数のKAISHAコードを扱うテーブルがあって、これを処理速度向上のため、 KAISHAコードごとにテーブルを分割し、 ALLKINGAKUテーブルを廃止して、代わりに select * from A01_KAISHA union all select * from A02_KAISHA ... としたALLKINGAKUビューを作成したと思ってください。 この時、Select * from ALLKINGAKU where KAISHA = 'A02'としたときに、ビュー上で、A01_KAISHAまで全件検索されてしまったことに 端を発している質問です)

  • Oracle
  • 回答数2
  • ありがとう数0

質問者が選んだベストアンサー

  • ベストアンサー
  • joih
  • ベストアンサー率35% (37/105)
回答No.1

うーん、混乱する質問ですね。整理すると、 (1)ALLKINGAKUビューが下記のとおり作成してある。  Select * from A01KINGAKU  union all  Select * from A02KINGAKU  union all  Select * from A03KINGAKU (2)A01KINGAKU、A02KINGAKU、A03KINGAKUテーブルにはそれぞれ KAISHA項目があり、インデクスが貼ってある。 (3)このビューに対して  Select * from ALLKINGAKU where KAISHA = 'A2'  と検索したら  A01KINGAKUテーブルを全件検索していた気がする。  A01KINGAKUテーブルを全件検索してないと思うには、  または該当するテーブルだけを検索するようにするにはどうしたらいいですか? という質問ですか? パーティションテーブルを使ったらどうでしょうか。 SQL実行計画は見ましたか? 全件検索(TABLE ACCESS FULL)ではなく索引検索(INDEX RANGE SCAN)になっていませんか?

kurinkurinkurin
質問者

補足

コメントありがとうございます。 はい、質問の意図はご指摘の通りです。 A01KINGAKU, A02KINGAKU , A03KINGAKUすべてが全件検索されています。 実行計画は確認しております。 パーティションテーブルは、Enterprise以上でないと使えないので このようなテーブル構成を自作しているようです。

その他の回答 (1)

  • SUPER-NEO
  • ベストアンサー率38% (706/1857)
回答No.2

こんにちは。 インデックスが意図した形で機能してくれない、 ということなんですが、オラクルでインデックスが機能しない ケースというのはご存知でしょうか? オラクルでは全レコード数の確か5%程度の結果が得られる場合に、 インデックス検索を行うというそうです。 つまり、極端な話ですと、1万件の中から9999件のレコードを 取得するのに、いちいちインデックスを使うよりも、 テーブルを総なめしたほうが高速である、ということです。 オラクルはこれを自動的に判断しています。 提示された例で考えると、テーブル内には1万社分のレコードが 登録されていて、テーブルに存在しないキーを条件につけた場合、 ということでの相談なっていますが、ただ単にレコードの有無だけを 判断するのでしたら、COUNT(キー項目)をとるのが良いと思います。 「*」を使うと、カーソルを使用したり、不要なフィールドへの アクセスが発生し、パフォーマンス的にも悪影響を及ぼします。 ですので、キー項目のカウントを取ることによって、 全体のパフォーマンスは向上すると思いますよ。 #1さんへの回答にありますように、索引の全体検索となっている だけですと、それが現状の最高パフォーマンスといえますが、 全表検索が走っているようであれば、そのテーブルの設計に問題が あるようにも感じられます。 現状1万件程度のデータで、どれくらいのパフォーマンスを発揮して いるのでしょうか? 私も色々とチューニングを経験してきましたけど、最もボトルネックが 潜んでいるといえるのが、実は実行する SQL 文だったりします。 あと最後にアドバイスですが、ビューは SQL 文を見やすくはしますが、 落とし穴になりがちです。 実際、SQL を実行した際には最初に実行されるのがビューの部分です。 ここで巨大な2つのテーブルを JOIN しているようなら、 そこがボトルネックになります。 2つのテーブルを、その段階で全表検索します。

関連するQ&A

  • 【初歩的な質問ですが・・・】 SQL文書き方がわかりません

    SQLの知識に乏しい者です。 よろしくお願い致します。 ●テーブルA ・会計コード ・年度 ・部署番号 ・社員番号 ・その他幾つかのデータ ※Where句で「年度>2002年」以降を抽出 のテーブルがあります。 この時、Bテーブルで ●テーブルB ・会計コード(主キー) ・年度 ・部署番号(主キー) ・社員番号(主キー) ・その他幾つかのデータ ※Aテーブルで抽出されたデータの中から絞り込む というテーブルを抽出するSQL文を組みたいのですが、効率の良いやり方がわかりません。 副問合せで  Select [B表で抽出した列名…]  From B表  Where 会計コード = (Select 会計コード               From A表               Where 年度 > '2002')  AND 部署番号 = (Select 部署番号             From A表               Where 年度 > '2002') ・・・・以下省略 の様に書くと効率が悪い気がしました。 (実際には、副問合せが6個書くことになるため) 良い書き方を知っている方がいらっしゃいましたら、よろしくお願い致します。

  • テーブル上に存在しないデータの一覧を取りたい。

    mysql+phpで開発を行っています。 テーブル id 101 102 104 106 109 110 の様にデータが入っているテーブルaaaがあります。 プログラムで取得したid一覧が上記テーブルにレコードがあるのか確認するSQLは 例)select id from aaa where id in (101,102) で取得できるということは分かっています。 ここで select id from aaa where id in (102,103) とやると102の1件が取得できます。 今回知りたいことは 逆に取得できなかった103という値を取得する方法はないのかという事です。 select id from aaa where id=102; select id from aaa where id=103; 2回SQLを実行して値が戻ってこないSQL=テーブルにそのレコードが無いというプログラムを書けばいい事は分かっています。 しかし、処理が少なくとも数千回発生してしまう予定ですのでできれば別の方法がいいと思っています。 また、in区で使っている一覧はテーブルには入っておらず、また、こちらも数千個あるので、一時テーブルに入れるといってもかなりの時間がかかってしまうと思います。 何か一発で取得できるいい方法などありますでしょうか? ちなみにaaaテーブルは5万件ほどなので全件php側でメモリに展開してサーチも避けたいです よろしくお願いいたします。

  • 4つのテーブルから、該当する項目を一度に検索したい。重複除く

    4つのテーブルから、それぞれ違う条件で検索し、該当する項目名NO を探したいのですが、どのようなselect文を書くと効率よく検索できる のでしょうか?また、重複NOは除きたいのです。 良かったら教えて下さい。 例えば、テーブル名:test1,test2,test3,test4とあった場合、 一度に該当するNOを拾い出す方法があれば、教えて下さい。 1.select no from test1 where code = '' and day < 20041118; 2.select no from test2 where day < 20041118; 3.2.select no from test3 where data != '' and day < 20041118; 4.select no from test4 where day > 20041018 and day < 20041118;

  • ACCESS97でSQLを使用して全データを順に取得したい

    ACCESS97を使用しています。 あるテーブルAの全データをモジュールを組んで textファイルへ出力したいのです。 1行ずつ取得して 1行ずつ出力する方法でやっています。  この時、1行ずつ取得したいのですが  strSQL = "SELECT * FROM テーブルA ;"  上記内容だと全件取得してしまいます。  1行ずつ 取得する方法はないのでしょうか?  例えば  strSQL = "SELECT * FROM テーブルA WHERE 1行目;"  又は、全件 textファイルに出力するモジュールあるのでしょうか?

  • select for updateのロック

    オラクルのselect for updateでロックをするタイミングがいつですか? こんなPL/SQLのコードがあったとします。 ---↓↓↓ソースコードここから↓↓↓------------------------- select * from テーブル1 where id = 1 for update; ・・・・・(a) ~ update テーブル1 set kingaku=100 where id = 1 ・・・・・(b) ~ commit; ---↑↑↑ソースコードここまで↑↑↑------------------------- id = 1のレコードがロックされるのは(a)、(b)どちらのタイミングですか? また、このロックは ・他トランザクションから読めるけど更新できない ・他トランザクションからは読むことすらできない のどちらでしょうか? よろしくお願いします。

  • SQLクエリ1年前のデータを削除できない

    現在このクエリを作成したのですがデータが削除されなくて、データ全件が抽出されてしまいます。 以下の構文で試したのですが・・・・もし、ご指摘、アドバイス等ございましたらよろしくお願いします。 select * from テーブル名 delete from テーブル名 where 日付 < = (select DATEADD(year,(-1),(日付))) ちなみに、日付はDATETIMEです   バージョン:SQL management studio 10.50.25.000

  • データ登録時、重複エラーを避けたい

    MYSQLのデータベースの、IDという項目が主キーのTESTというテーブルに、データをに登録する際、 既に主キーが同じデータがない場合に、という条件をつけたいのですが、 下のように書くと、エラーになってしまいます。 INSERT INTO TEST (ID, NAME) VALUES ('a', 'abc') WHERE NOT EXISTS (SELECT * FROM TEST WHERE ID = 'a'); どうしたらよいか教えてください。

    • ベストアンサー
    • MySQL
  • 複数のテーブルから同じ条件で検索したい。

    例えば、テーブルがA,B,C,Dとあって、レイアウトはそれぞれ違います。 ですが、全てのテーブルに共通の項目もあります。 共通項目名:FLG このような前提で、 A,B,C,Dのデータを同じ検索条件で全ての内容を表示させたいのですができませんか? ベタに書くと select * from A where FLG='2'; select * from B where FLG='2'; select * from C where FLG='2'; select * from D where FLG='2'; と言う感じで結果を表示させたいのです。 実際にはテーブル名がものすごい数なので、ベタに書きたくないので、この部分をtab テーブルのtnameとかを使っていっぺんに検索結果が出せればありがたいのですけが・・・ こういうのはシェルとか使わないとだめですかね?(DBはオラクルです。)

  • WHERE句の条件の記述の順序

    PRIMARY KEYとINDEXがテーブルに設定されている場合、 検索条件に記述する順番はどのようになるのでしょうか? 下記のテーブルがあり、SELECT文をつくろうと 考えています。 テーブル:foo 項目  PRIMARY KEY  INDEX ----------------------------------- a 1 b 2 1 c 3 d 2 (1)PRIMARY KEYを優先してWHERE句の順番を決める↓ SELECT * FROM foo WHERE a = "AAA" AND b = "BBB" AND c = "CCC" AND d = "DDD" (2) それともINDEXが設定されている項目を先に記述する↓ SELECT * FROM foo WHERE b = "BBB" AND d = "DDD"   AND a = "AAA" AND c = "CCC" (1)と(2)ではどちらの性能がよいのでしょうか?

  • NULLで検索を行ったときは全件表示させたい

    VWD2008で簡単なDB検索アプリケーションを作成しています。 ページ内に Textboxコントロール(Textbox1)とButtonコントロール GridViewコントロール(GridView1)を配置しています。 データベース列の要素は id(番号) name(商品名) value(数量) として、テーブルの内容には下記内容が入力されています。 ------------------------- id    name   value 1    AAAA   1 2    AAAB   2 3    DDDD   3 -------------------------- テキストボックスに商品名を入力して、該当する商品だけを抽出させるのですが テキストボックスに何も入力せずに検索ボタンを押したときは すべてのDBの内容を表示させたいのです。 今のところ何も入力せずに検索しなかった場合はGridView上には 何も結果が出力されません。 GridViewのデータソースの構成によりWhere句の追加で 列:name 演算子:LIKE ソース:Control パラメータのプロパティ:TextBox1 規定値:何も入力せず(NULL?) と入力して追加ボタンを押すと以下のWHERE句が追加されました。 SELECT id, name, value FROM Table1 WHERE    ([name] LIKE '%' + @name + '%')) NULLで検索を行った場合に全件表示させたい場合 WHERE句はどのように設定するのが好ましいのでしょうか・・・、、 初歩的な質問で大変申し訳ありませんが教えてください。困っています。