2012-03-14 45 views
1

我有一個查詢不能執行,因爲我希望它執行。我幾乎在所有頁面上都使用它來在頁腳中顯示4位隨機輔導員和他們相關的一些數據(他們的名字,他們的頭像以及他們提供的課程數量)。改進此查詢,在Oracle中使用3個連接,也許使用「分區」?

如何在Oracle中提高此查詢的執行速度?我正在看分區和使用分區和其他的東西。我有一個mySQL背景,我可能沒有充分利用Oracle。

我有以下表結構:

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 2012-03-15 14:30:58

+0

該查詢應該從數據庫中獲得4個隨機輔導者,他們有多少課程,他們的個人資料頭像 – Mythriel 2012-03-15 14:45:06

回答

2

對於初學者 - 如何是你的指數?

你應該有

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

(其實之前也許這)指標,什麼是解釋計劃的表現?

表中有多少條記錄?

+0

500條記錄,我沒有索引,我使用PHP和Oracle,並且無論如何都會使用memcache來緩存結果 – Mythriel 2012-03-14 17:08:13

+0

你會更好地生成4個隨機的導師(他們可能有其他需求,而不是「導師」),然後生成他們需要的數據。 – 2012-03-14 18:04:02

+0

您使用的是Oracle的SQL * Developer產品嗎?它在工作表編輯器中有一個非常好的EXPLAIN PLAN按鈕。 – 2012-03-14 18:04:27

2

由於Andy Finkenstadt建議您最好選擇4位隨機輔導員,然後從剩餘的結果集中選擇4個隨機值。雖然這意味着您通過dbms_random.value兩次訂購 - 這看起來更糟糕 - 但這確實意味着您要進行訂購的數據集要小得多。

您還應該確保按照Randy's answer有索引。

忌諱的"生產套管列名,除非你有一個非常之所以這樣是從未值得額外的麻煩,它會導致。你將永遠不得不引用他們的引子。

如果你想使用分析功能,這會加快東西,你應該在選擇添加distinctcountcount(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行。但另一方面,如果行數非常少,則執行全表掃描可能會更快,而不是一次讀取幾個塊。 – 2012-03-15 05:06:22

+0

aaa ...這個查詢比我的第一個查詢運行更差 – Mythriel 2012-03-15 09:18:08

+0

@Mythriel,第6個字是_may_ :-)。您是否創建了索引緩存將僅在第一次運行後才起作用? – Ben 2012-03-15 09:23:34