• ベストアンサー
  • すぐに回答を!

ORACLEでwhere句の検索順序

Oracle9i windows2000です。 以下のようなテーブルがあります。 table_a ----------------------- id   NUMBER(10,0) NOT NULL, sort   NUMBER(10,0) NOT NULL, name   VARCHAR(10), text   VARCHAR(255) この条件で、以下のふたつのSELECT文を発行した時、パフォーマンスが良いのはどちらですか? Oracleでは後ろから検索されると聞いたことがあるのですが本当でしょうか? ※idにプライマリキー、 id,sortにインデックスが貼ってあります。 (1)SELECT text FROM table_a WHERE id = 1 AND sort = 2 AND name = 'a' (2)SELECT text FROM table_a WHERE name = 'a' AND sort = 2 AND id = 1

共感・応援の気持ちを伝えよう!

  • 回答数6
  • 閲覧数938
  • ありがとう数9

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

  • ベストアンサー
  • 回答No.5

こんにちわ。 #3 のmuyoshid です。 > 「オプティマイザを使用しているのであれば」 > ということは、必ずオプティマイザが使われるわけでは > ないのでしょうか。 Oracle9i の場合、コストベース・オプティマイザと ルールベース・オプティマイザの2種類のオプティマイザ が実装されています。 簡単に説明すると、 ルールベース・オプティマイザ:  検索に使用する索引の優先順位や、結合方法に優先順位  が決められていて、優先順位の高いものから選択される  ようになっています。 コストベース・オプティマイザ:  テーブルをAnalyze して収集した統計情報に基いて  アクセスパスが決定されます。  Materialized View やFunction 索引等、  コストベース・オプティマイザの使用が前提となっている  機能もいくつかあります。 ユーザ登録 (無料) が必要ですが、OTN Japan でPDF 形式の マニュアルを公開していますので、詳細はこちらで確認 されてみてはいかがでしょうか? 「Oracle9i パフォーマンスチューニング・ガイドおよびリファレンス」 に詳しく記載されています。

参考URL:
http://otn.oracle.co.jp/

共感・感謝の気持ちを伝えよう!

質問者からのお礼

お礼が遅くなり申し訳ございませんでした。 大変参考になりました。

関連するQ&A

  • 見たことのないINSERT文

    お世話になります。 他人の書いたSQLを解析して以下のようなコードを見つけました。 CREATE TABLE OYA ( ID NUMBER NOT NULL, NAME VARCHAR2(10) ) / CREATE TABLE KO ( ID NUMBER NOT NULL, OYA_ID NUMBER NOT NULL, NAME VARCHAR2(10) ) / INSERT INTO ( SELECT ID ,OYA_ID ,NAME FROM KO WHERE EXISTS ( SELECT ID FROM OYA WHERE NAME LIKE '%1' ) ) VALUES ( 1 ,1 ,'KODOMO-1' ); INSERT文でテーブル名を指定するかわりにSELECT文を指定しています。 SELECT INSERT文は知っていますが、このような表記は初めてです。 (文法エラーにならないのに驚きました) おそらく意図するところは、ある条件に一致したOYAが存在する場合に、KOをインサートするのだと思いました。 実際は、OYAがなくてもINSERTは実行されてしまいますが。。。 このような表記のINSERT文の説明が書いてあるサイトをご存知の方がいらっしゃいましたら、よろしくお願いします。

  • 副問合せ 続(Oracle SQL)

    問題:NATION表とINVENTION表より人口密度(人口/面積)が100以下の国で、発明事項がある国の国コードを表示する。 方法1:主問合せでNATION表を利用する 方がうまくいきません。 私の考えた下記SQL文では実行結果が80件返ってしまいます。 答えは方法2と同じ5件ですがどこが悪いのでしょうか? 回答のほどよろしくお願い致します。 方法1:主問合せでNATION表を利用する SELECT CODE FROM NATION WHERE (POPULATION / AREA) <=ANY(SELECT 100 FROM INVENTION) SELECT CODE FROM NATION WHERE POPULATION / AREA < 100;(上と同じ意味) INVENTION表の副問合せがうまくできていないので5件出力できない? 方法2:主問合せでINVENTION表を利用する SELECT DISTINCT NATION_CODE FROM INVENTION WHERE NATION_CODE = ANY(SELECT CODE FROM NATION WHERE 100 >= POPULATION / AREA) NATION_CODE ----------- 107 136 142 154 157 各表の構造はこのようになります。 SQL> DESCRIBE INVENTION 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- INVENTION NOT NULL VARCHAR2(30) INVENTOR VARCHAR2(30) YEAR NUMBER(4) NATION_CODE NUMBER(4) SQL> DESCRIBE NATION 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- CODE NOT NULL NUMBER(5) NATION NOT NULL VARCHAR2(28) CAPITAL VARCHAR2(20) AREA NUMBER(22) POPULATION NUMBER(22)

  • あいまい検索の仕方で・・・

    SELECT 担当, 商品, 売上品 FROM TableName WHERE 担当 IN (SELECT 担当 FROM TableName WHERE 売上品 = '竹輪') AND 担当 IN (SELECT 担当 FROM TableName WHERE 売上品 = '胡瓜') AND 売上品 IN ('竹輪','胡瓜') とサブクエリで出したいものが出ますが・・・あいまい検索にしたいと思っています。 SELECT 担当, 商品, 売上品 FROM TableName WHERE 担当 IN (SELECT 担当 FROM TableName WHERE 売上品 like '%竹輪%') AND 担当 IN (SELECT 担当 FROM TableName WHERE 売上品 like '%胡瓜%') AND 売上品 IN ('竹輪','胡瓜') まではわかるのですが売上品 IN ('竹輪','胡瓜')はどうすればよいのでしょうか?

その他の回答 (5)

  • 回答No.6

>インデックスを貼ってなかった場合 >(idのみ)はどうなるのでしょうか。 もちろんオプティマイザに依存するのですが、 依存しても インデックス以外の項目 が存在するだけで、 コストが5倍かかるといっても 過言ではありません。 8i以降その傾向が顕著になってきました。 5万件のデータリードだけで、 30分かかってしまうこともあります。 特にODBCなどを介して、 RDO,ADOを利用する場合は 注意が必要です。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

お礼が遅くなり申し訳ございませんでした。 大変参考になりました。

  • 回答No.4
  • jmh
  • ベストアンサー率23% (71/304)

場合によっては、  where my_slow_funxion(name) = 1 and name = 'a' の方が  where name = 'a' and my_slow_funxion(name) = 1 よりも 速かったような気がします(逆?)。 もし、試してみていただけるのなら、結果を教えていただけると嬉しいです。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

お礼が遅くなり申し訳ございませんでした。 大変参考になりました。

  • 回答No.3

こんにちわ。 ルールベース・オプティマイザを使用しているのであれば通常の索引を使用した検索 よりも主キーによる検索の方が優先度が高いので、主キーが使われます。 と言う事で、どちらのSQL 文でもパフォーマンスは同じはずです。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

ご回答有難うございます。 「オプティマイザを使用しているのであれば」 ということは、必ずオプティマイザが使われるわけではないのでしょうか。 索引よりも主キーの優先度が高いのですね。 #2の方と逆の説になってしまい、ますます悩んでしまいます・・。 主キー優先となった場合に、where句での書き順はどちらでも同じ、というのはどうしてなんでしょう? 先に書いたほうが早い、とか後に書いたほうが早い、とかいう概念自体が間違っているのでしょうか。 もしよろしければひきつづきご回答いただけないでしょうか。

  • 回答No.2

select /*+ index(table_a インデックス名) */ text from table_a where id = 1 and sort = 2 and name = 'a' とすれば Where句をどう変えようと 指定されたインデックスを 一番最初に見るので パフォーマンスが一番いいです。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

ご回答有難うございます。 インデックスを貼ってある場合はインデックス優先なんですね。 ではインデックスを貼ってなかった場合 (idのみ)はどうなるのでしょうか。 もしよろしかったら引き続きご回答いただけないでしょうか。

  • 回答No.1
  • mi-si
  • ベストアンサー率35% (200/567)

Oracleはオプティマイザが働いて、最適な実行順序に組み替えてしまうので、実際にどのような順序で実行されているかは解りません。 EXPLAIN PLANで実際の実行順序を調べてみたらどうでしょうか?

参考URL:
http://oracledba.at.infoseek.co.jp/dba/contents/explainplan.htm

共感・感謝の気持ちを伝えよう!

質問者からのお礼

ご回答有難うございます。 実際の順序で実行されるかはわからないのですね。 EXPLAIN PLANというのも明日さっそくやってみます。

関連するQ&A

  • 2つのテーブルからデータ取得

    いつもお世話になっております。 以下のようなテーブルがあります。 ---------- CREATE TABLE IF NOT EXISTS `students` ( `id` int(11) NOT NULL AUTO_INCREMENT, `student_number` bigint(20) DEFAULT NULL, `name` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, PRIMARY KEY (`id`) ) ---------- CREATE TABLE IF NOT EXISTS `student_upload` ( `student_number` bigint(20) NOT NULL, `upload_id` int(11) NOT NULL ) ---------- データは以下のように登録されています。 students ---------- id|student_number|name 1 |11111     |いちろう 2 |22222     |じろう 3 |33333     |さぶろう student_upload ---------- student_number|upload_id 11111     |1 11111     |2 22222     |1 22222     |2 ---------- student_upload.upload_id=1 のデータを取得したいので 下記のようなSQL文を発行しているのですが、student_upload.upload_id=2 の データも取得されてしまいます。 select * from students s, student_upload up where up.upload_id=1 and up.student_number=s.student_number よろしくご教示お願いいたします。 <環境>  PHP:5.3.5  MySQL:5.0.7

    • ベストアンサー
    • MySQL
  • もうちょっと賢いSELECT文が書けないものでしょうか

    初めまして、最近SQLをかじり始めたぺーぺーです。 効率の悪いSELECT文しか書けずに困っています。 下記のテーブルsoftware_tableから、 ・name列「oracle」 ・version値が最大 のレコードに含まれるid(=3)を拾ってきたいのですが、自分の頭では副問い合わせを使う方法か、ソートを使う方法しか思いつきません。 問題は副問い合わせ・ソートを使うと計算コストが大きくなってしまうことで、できることなら副問い合わせ・ソートを使わずに解決したいのですが、何か方法はないものでしょうか? よろしくお願い致します。 ----------------------------- software_table id name version 1 oracle 1 2 oracle 2 3 oracle 3 4 postgres 1 5 postgres 2 6 postgres 3 7 postgres 4 ----------------------------- ■副問い合わせを使った方法 SELECT id FROM software_table WHERE name = 'oracle' AND version = (SELECT max(version) FROM software_table WHERE name = 'oracle'); ■ソートを使った例 SELECT id FROM software_table WHERE name = 'oracle' ORDER BY version DESC LIMIT 1 OFFSET 0; -----------------------------

  • Oracle SQLの、where句内の条件文について教えてください。

    Oracle SQLの、where句内の条件文について教えてください。 下記SQLの(1)と(2)の記述文を教えてください。 (1)例:owner = sys,admin ownerがsysまたは、adminを抽出 (2)例:column_name = '*aaa*' column_nameに「aaa」が含まれているデータ SELECT owner, table_name,column_name FROM all_tab_columns WHERE (1)(Ownerを複数指定)   and (2)(column_nameに、●●が含まれるデータ)

  • TO_NUMBERの結果は、カラムに追加できない?

    いつもお世話になっています。 TO_NUMBER実行時、結果はnumeric型で取得できると思うのですが、 その値をカラムに追加することはできるのでしょうか? insert into number2 values((select numberStr,TO_NUMBER (numberStr,'000.000') from number),'aaa'); 実行すると、 副問い合わせは1列のみを返さなければなりませんというErrorが生じます。 なのでwhere句を追加しましたが、結果は同じです。 実行したsqlは、 create table number ( count integer not null primary key, numberStr varchar(20) not null ); create table number2 ( no numeric not null primary key, numberS varchar(30) not null); insert into number values(5,'555.55000'); insert into number2 values((select numberStr,TO_NUMBER (numberStr,'000.000') from number where count=5),'aaa'); です。 宜しくお願いします。

  • エラー「無効な識別子です」

    ORA-00904: "EMPNO": 無効な識別子です と表示されます。 解決方法知っている方、教えていただければ幸いです。 SELECT EMPNO, ENAME, D.DEPTNO, DNAME FROM DEPT D WHERE EMPNO = (SELECT EMPNO FROM EMP WHERE MGR IS NULL) SQL> DESCRIBE EMP; 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NOT NULL NUMBER(2)

  • Oracle8のトップN解析

    質問させていただきます。 Oracle8iの場合、トップN解析ということで select id, name from (select id, name from tmp order by id desc) where rownum <= 3; というSQLを作成してidを前から3つだけ検索できますが、 Oracle8の場合、インラインビューでの[order by]が 無効なので、困っています。 よければ、ほかの方法はないものでしょうか?

  • テーブル結合で、結合フィールドをWHERE句に用いた時に、結合フィールドのデータがNULLになってしまう。

    MySQL 4.0.24-standard + PHP Version 4.3.11 を使用しています。 下記のような table_a, table_b があり、idフィールドで外部結合させています。 table_a id|value ------- 1 | 0 2 | 1 table_b id|name ------- 1 | A 2 | B SELECT * FROM table_a NATURAL LEFT OUTER JOIN table_b; result id|value|name -------------- 1 | 0 | A 2 | 1 | B しかし、下記のクエリでは、このようにidがNULLになってしまいます。 SELECT * FROM table_a NATURAL LEFT OUTER JOIN table_b WHERE table_a.id = 1; result id |value|name -------------- NULL| 0 | A 以下のような結果を得たいのですが、どうすれば良いのでしょうか? result id|value|name -------------- 1 | 0 | A

    • ベストアンサー
    • MySQL
  • エラー2「無効な識別子です」

    ORA-00904: "D"."DEPT": 無効な識別子です。 先ほども似たような質問をしましたが原因がよく分からないなのでご存知の方教えていただければ幸いです。 SELECT D.DEPTNO, E.ENAME, E.SAL FROM EMP E, DEPT D WHERE E.SAL >ANY (SELECT MAX(E.SAL) FROM DEPT D, EMP E GROUP BY D.DEPT) SQL> DESCRIBE EMP; 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NOT NULL NUMBER(2) SQL> DESCRIBE DEPT; 名前 NULL? 型 ----------------------------------------- -------- ---------------------------- DEPTNO NOT NULL NUMBER(2) DNAME VARCHAR2(14) LOC VARCHAR2(13)

  • Oracleのシーケンスありのテーブル作成について

    Oracleのテーブルを作るのに、ある列を自動で「全体の通し番号」みたいなユニーク(一意)な番号を振りたいく、 シーケンス(sequence)を作成しテーブルを作ろうとしているのですがうまくいきません。 どこがわるいのでしょうか。 create sequence "yamaaf_seq"; CREATE TABLE TBL_AFFILIATE_SESS( UNIQ_ID NUMBER(11,0) DEFAULT nextval('yamaaf_seq') NOT NULL, ORG_CODE VARCHAR2(64) NOT NULL, primary key("UNIQ_ID"));

  • selectで特定の列をwhereで指定するとエラーになる

    今MYSQLのselect文でエラーが出ていて、where でgroupを指定するとエラーが出ます。どこかの書き方が間違っているようなのですが、正しい書式を教えていただけないでしょうか? 色々と実験してみて同じ書き方でほかの列を検索したときは検索が出来ることがわかったので、どこを直していいのかわからない状態です。 環境はWinXP Home SP2 MySQL 5.0.27-community-nt です。 操作しているテーブルは以下の通りで、IDやscodeを検索しようとすると正常に表示されます。 CREATE TABLE `product` ( `ID` int(11) default NULL, `id_seq` int(11) default NULL, `scode` varchar(50) default NULL, `rec_ctl` varchar(10) default NULL, `dir` varchar(100) default NULL, `image` varchar(100) default NULL, `image_s` varchar(100) default NULL, `brand` varchar(100) default NULL, `goods` varchar(100) default NULL, `group` varchar(50) default NULL ); 実行したSQL文と結果です。 mysql> select * from product where group = 'a'; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group = 'a'' at line 1 IDなどであれば検索が出来ます。 mysql> select * from product where id = 'a'; Empty set (0.00 sec) それではよろしくお願いいたします。

    • ベストアンサー
    • MySQL