2009-07-29 23 views
4

嘿,我有一個查詢需要優化。它的作品,但它的狗,表現明智。如何優化MySQL查詢(羣組和訂單)

它讀取這樣的:

SELECT * 
FROM (
     SELECT * 
     FROM views 
     WHERE user_id = '1' 
     ORDER BY 
       page DESC 
     ) v 
GROUP BY 
     v.session 

我跟蹤的觀點不同的頁面,我想知道每節最高的頁面,才能知道他們已經通過點擊多遠(他們」在任何給定的會話中,都需要查看每一頁到最後)。

基本上我想要做的是在集團之前對結果進行排序。以上成本高昂,成本高昂。

任何人誰可以拍我頭如何做到這一點?多謝你們!

更新:

的解釋:

"1" "PRIMARY" "<derived2>" "ALL" \N \N \N \N "3545" "Using temporary; Using filesort" 

"2" "DERIVED" "views" "index" \N "page" "5" \N "196168" "Using where" 

的模式:

ID  int(8) unsigned (NULL)  NO  PRI  (NULL) auto_increment select,insert,update,references   
page  int(8)   (NULL)  YES  MUL  (NULL)     select,insert,update,references   
user_id int(8)   (NULL)  YES    (NULL)     select,insert,update,references   
session int(8)   (NULL)  YES    (NULL)     select,insert,update,references   
created datetime   (NULL)  NO          select,insert,update,references  

指數信息:

views   0 PRIMARY    1 ID   A    196008 (NULL) (NULL)   BTREE  

views   1 page     1 page   A     259 (NULL) (NULL) YES  BTREE 
+0

請求mysql性能優化時,請始終提供以下內容。 1.查詢2. EXPLAIN查詢輸出3.爲所有適當的表顯示CREATE TABLE。謝謝。 – hobodave 2009-07-29 16:03:30

+0

你可以在你的模式上發佈一些細節嗎? – Macros 2009-07-29 16:04:12

回答

8

我正在跟蹤不同頁面的視圖,我想知道每個會話的最高頁面,以便知道他們點擊的距離(他們需要查看每個頁面在任何給定的會話中結束)。

在分組之前進行排序是非常不可靠的方法。

MySQL延伸GROUP BY語法:您可以使用SELECTORDER BY子句中的未分組和未分組字段。

在這種情況下,每session輸出隨機值page

Documentation明確規定,你不應該讓哪個值完全不會是任何假設:

如果從GROUP BY部分省略列不在組中恆不要使用此功能。服務器可以自由地返回組中的任何值,所以結果是不確定的,除非所有值都相同。

但是,在實踐中,返回掃描的第一行的值。

由於您在子查詢中使用ORDER BY page DESC,因此此行恰好是每個會話最多有page的行。

你不應該依賴它,因爲這種行爲是沒有記錄的,並且如果在下一個版本中將返回一些其他行,它將不被視爲一個錯誤。

但你甚至不必做這樣的討厭的技巧。

只需使用聚合函數:

SELECT MAX(page) 
FROM views 
WHERE user_id = '1' 
GROUP BY 
     session 

這是記錄和清潔的方式做你想做的。

(user_id, session, page)創建複合索引,以便查詢運行得更快。

如果您需要從表中的所有列,不僅聚合的,使用此語法:

SELECT v.* 
FROM (
     SELECT DISTINCT user_id, session 
     FROM views 
     ) vo 
JOIN views v 
ON  v.id = 
     (
     SELECT id 
     FROM views vi 
     WHERE vi.user_id = vo.user_id 
       AND vi.session = vo.session 
     ORDER BY 
       page DESC 
     LIMIT 1 
     ) 

這是假定idviews一個PRIMARY KEY

0

我想小號在user_id頁面上使用一個複合(多列)索引。這假定內部查詢是緩慢的部分。

0

問題是子選擇。 SELECT * FROM(SELECT * FROM)

您應該使用連接。什麼數據類型是你的'頁面'字段?

4

我認爲你的子查詢是不必要的。你會從這個更簡單,速度更快的查詢得到同樣的結果:

SELECT * 
FROM views 
WHERE user_id = '1' 
GROUP BY session 
ORDER BY page DESC 

此外,你應該有你要麼分組,排序或「地方-ING」,由各個領域的指數。在這種情況下,您需要user_id,會話和頁面上的索引。