2012-03-14 3 views
1

私はそれが実行したいと思うように実行していないクエリがあります。ほとんどすべてのページでフッターに4人のランダムなチューターと関連データ(名前、アバター、提供するコース数)のリストを表示します。Oracleで3つの結合を使用するこのクエリを改善しました。多分 "partition over"を使用していますか?

Oracleでこのクエリの実行速度を改善するにはどうすればよいですか?私はパーティションを見ていて、パーティションを使用していました。私はmySQLのバックグラウンドを持っており、私はおそらくOracleを最大限に活用していないでしょう。

I持って、次のテーブル構造:

tutor_profiles: 
    id 
    user_id (FK users) 

users: 
    id 
    username 
    avatar_id (FK files) 

courses: 
    id 
    tutor_id (FK tutor_profiles) 
    description 
    ... 

    files 
     id 
     file_uri 

`

そして、私はこのクエリがあります初心者のための

SELECT * FROM 
    (SELECT inner_query.*, rownum rnum 
    FROM (
     SELECT tutor_profiles.id AS "tutor_id" 
      , tutor_profiles.full_name AS "full_name" 
      , files.file_uri as "file_uri" 
      , files.id AS file_id 
      , tutor_profiles.user_id 
      , count(distinct courses.id) AS "course_count" 
     FROM tutor_profiles 
      LEFT JOIN users ON users.id = tutor_profiles.user_id 
      LEFT JOIN files ON files.id = users.avatar_id 
      LEFT JOIN courses ON tutor_profiles.id = courses.tutor_id 
     GROUP BY tutor_profiles.id, tutor_profiles.full_name, tutor_profiles.user_id, files.file_uri, files.id 
     ORDER BY dbms_random.VALUE 
    ) inner_query 
    WHERE rownum <= 4) 
+0

実行するクエリは何ですか? – Luke101

+0

質問はデータベースから4人のランダムなチューターを取得する予定です。プロフィールのアバター – Mythriel

答えて

2

- どのようにあなたのインデックスがあるの?

あなたは(実際には多分その前に)その後

users.id 
files.id 
tutor_profiles.user_id 
tutor_profiles.id 
courses.tutor_id 
users.avatar_id 

のインデックスを持つ必要があり、実行計画の上映は何ですか?

おおよそのテーブルのレコード数は?

+0

500レコード、私はインデックスを持っていません。私はオラクルでPHPを使用していますが、結果をキャッシュするのにmemcacheを使用します。 – Mythriel

+0

あなたは4人のランダムなチューター(「家庭教師」よりも他の要件を持つかもしれない)を生成し、それらから必要とされるデータを生成するほうがはるかに良いでしょう。 –

+0

OracleのSQL * Developer製品を使用していますか?ワークシートエディタにEXPLAIN PLANボタンがあります。 –

2

Andy Finkenstadtは、4人のランダムなチューターを選択し、残りの結果セットから4つのランダムな値を選択するほうがよいと提言しました。これは、dbms_random.valueで2回注文していることを意味しますが、悪化しています。これは、この注文を行っているデータセットがはるかに小さいことを意味します。

また、Randy's answerのようなインデックスがあることを確認する必要があります。それは決してそれが引き起こす余分な手間の価値があるあなたは、このために非常に正当な理由がない限り

ペットpeeve、"は、同棲列名を生成します。あなたはいつも逆のカンマでそれらを参照する必要があります。

あなたがcountで選択してdistinctを追加する必要があり、物事をスピードアップし、count(distinct c.id) over()count(distinct c.id)を交換することができる分析機能を使用して、試してみたい場合。つまり、すべての行についてdistinctidとカウントしています。 partition by句を追加した場合は、パーティション内のすべてのものに対してこのカウントを行います。 group byも完全に削除する必要があります。

追加のサブ選択も削除しましたが、これは必須ではありませんでした。

select * 
    from (select tp.id as tutor_id 
       , tp.full_name as full_name 
       , f.file_uri as file_uri 
       , f.id AS file_id 
       , tp.user_id 
       , count(distinct c.id) as course_count 
      from (select * 
        from (select id 
           , full_name 
           , user_id 
          from tutor_profiles 
          order by dbms_random.value) 
        where rownum <= 4) tp 
      left outer join users u 
      on u.id = tp.user_id 
      left outer join files f 
      on f.id = u.avatar_id 
      left outer join courses c 
      on tp.id = c.tutor_id 
      group by tp.id, tp.full_name, tp.user_id, f.file_uri, f.id 
      order by dbms_random.value) 
where rownum <= 4 
+0

また、最初のテーブルのランダムサンプルを使用してパフォーマンスを向上させることもできます。例: 'from tutor_profiles sample(5)'です。適切なサンプルの割合を選ぶのは難しいことがあります。できるだけ小さなデータを取得するには小さなパーセンテージを必要としますが、少なくとも4行を確保するには十分な数の番号が必要です。ただし、行数が非常に少ない場合は、1ブロックずつ読み取るのではなく、フル・テーブル・スキャンを行う方が高速になる場合があります。 –

+0

aaa ...このクエリは私の最初のクエリよりも悪いです。 – Mythriel

+0

@マイリスリエル、6番目の単語は_may_です:-)。最初の実行後にのみキャッシュが機能するインデックスを作成しましたか? – Ben

関連する問題