簡體   English   中英

如何優化MySQL查詢(組和順序)

[英]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語法:您可以在SELECTORDER 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
        )

這假設idviews上的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM