2015-09-02 73 views
0

我有以下查詢,大約需要15秒才能執行。如果我刪除了ORDER BY,則需要3秒鐘,這仍然太長。MySQL用左連接查詢,按極慢排序

SELECT 
pages.id AS id, 
pages.page_title AS name, 
SUM(visitors.bounce) AS bounce, 
SUM(visitors.goal) AS goal, 
count(visitors.id) AS volume 
FROM 
pages 
LEFT JOIN visitors ON pages.id = visitors.page_id 
GROUP BY pages.id 
ORDER BY volume DESC 

爲了增強可讀性,我稍微簡化在應用程序中使用的此查詢,但我一直在用這個簡單的查詢測試和問題也依然存在。所以問題在於這一部分。

表頁:約3K記錄。表訪問者:大約30萬條記錄。

我做了什麼:

  • 我有visitors.page_id指數(外部鍵鏈接到pages.id)。
  • 顯然我的ID字段被設置爲主鍵。

我曾嘗試:

  • 我增加了read_buffer_size,sort_buffer_size的值,read_rnd_buffer_size,爲64M。
  • EXPLAIN與排序查詢(15秒): enter image description here
  • EXPLAIN查詢,而無需排序(3秒,靜止的方式來長,這不是我想要的輸出): enter image description here
  • 取出SUM和Count計算,他們並沒有對執行時間產生影響。

改進此查詢的任何想法?

+0

數據庫不能神奇地使一切都變得更快。您的查詢需要完整掃描2個表,因爲無論您做什麼,它都必須獲取所有行。這將需要幾秒鐘的時間爲一個300k排桌子。此外,計劃似乎顯示'WHERE'子句,即使您的查詢沒有。你確定你確切地解釋了這個查詢嗎?你能每隔幾分鐘緩存一次結果,並把它交給客戶端嗎? – jpmc26

+0

它確實有點複雜,用戶可以設置一些過濾器,但它們似乎沒有影響查詢的速度,所以我在本例中刪除了它們。但maby不是簡化我的問題,而是讓它變得不那麼簡單,對不起。 由於用戶可以設置這些設置,緩存很難(數百個選項)......您認爲如果我用完整查詢提出新問題會更好嗎?我認爲只要這個基本的例子很慢,那就需要先解決。但我現在明白,過濾器實際上可以使其更快...... – dirk

+0

過濾器可以提供索引選項。分頁加索引也可能有幫助。兩者都提供了用於限制數據庫必須處理的結果集大小的選項。雖然由於您想按結果進行排序,但分頁對於您來說可能還不夠。 – jpmc26

回答

1

首先,嘗試 我的第一個建議是在連接前做了彙總:

SELECT p.id, p.page_title AS name, 
     v.bounce, v.goal,v.volume 
FROM pages p LEFT JOIN 
    (SELECT page_id, sum(v.bounce) as bounce, sum(v.goal) as goal, 
      count(*) as volumn 
     FROM visitors v 
     GROUP BY page_id 
    ) v 
    ON pages.id = v.page_id 
ORDER BY volume DESC; 

然而,你的查詢需要做兩件事聚集和排序 - 你有沒有過濾。我不確定你能否快得多。

+0

謝謝。這有很大的不同。再加上我的帖子發表的評論(實際上有一些過濾,我簡化這個問題並不聰明),我可以從這裏解決。謝謝! – dirk