[英]How to optimize MySQL query (group and order)
嘿所有,我有一個需要優化的查詢。 它有效,但它是一只狗,性能明智。
它看起來像這樣:
SELECT *
FROM (
SELECT *
FROM views
WHERE user_id = '1'
ORDER BY
page DESC
) v
GROUP BY
v.session
我正在跟蹤不同頁面的視圖,我想知道每個會話的最高頁面,以便知道他們在任何給定的時間點擊了多遠(他們需要一直查看每個頁面)會話。
基本上我要做的是在GROUP之前對結果進行排序。 以上實現了這一點,成本很高。
任何人都可以拍我的頭腦怎么做? 多謝你們!
更新:
解釋:
"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
我正在跟蹤不同頁面的視圖,我想知道每個會話的最高頁面,以便知道他們在任何給定的時間點擊了多遠(他們需要一直查看每個頁面)會話。
在分組之前進行排序是一種非常不可靠的方法。
MySQL
擴展了GROUP BY
語法:您可以在SELECT
和ORDER BY
子句中使用未分組和未分段的字段。
在這種情況下,每個session
輸出一個隨機的page
值。
文檔明確指出,您永遠不應該對它的確切值做出任何假設:
如果從
GROUP BY
部分省略的列在GROUP BY
中不是常量,請不要使用此功能。 服務器可以自由地從組中返回任何值,因此除非所有值都相同,否則結果是不確定的。
但是,實際上,將返回掃描的第一行的值。
由於您在子查詢中使用ORDER BY page DESC
,因此該行恰好是每個會話具有最大page
的行。
您不應該依賴它,因為此行為未記錄,如果在下一版本中將返回其他行,則不會將其視為錯誤。
但你甚至不必做這些討厭的伎倆。
只需使用聚合函數:
SELECT MAX(page)
FROM views
WHERE user_id = '1'
GROUP BY
session
這是記錄和干凈的方式來做你想要的。
在(user_id, session, page)
上創建一個復合索引(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
)
這假設id
是views
上的PRIMARY KEY
。
我認為你的子查詢是不必要的。 您將從這個更簡單(更快)的查詢中收到相同的結果:
SELECT *
FROM views
WHERE user_id = '1'
GROUP BY session
ORDER BY page DESC
此外,您應該在每個字段上都有一個索引,您要么對其進行分組,排序或“在哪里”。 在這種情況下,您需要有關user_id,session和page的索引。
我會在user_id頁面上建議一個復合(多列)索引。 這假設內部查詢是緩慢的部分。
問題是子選擇。 SELECT * FROM(SELECT * FROM)
您應該使用聯接。 您的“頁面”字段是什么數據類型?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.