簡體   English   中英

mySQL查詢分組記錄的前N個條目

[英]mySQL query for top N entries of a grouped records

我是MySql和一般數據庫的新手。 我有一個查詢,我通過在線資源和跟蹤和錯誤的片段一起構建。 它真的很慢(27秒),我認為它可以優化。 也許有人可以幫我解決這個問題。

這是mySQL的數據結構 - 數據庫。 版本5.1.51-0

|- purchaseID -|- customerID -|- emotionID -|- customerCountryCode -|- customerContinentCode-|
|     1        |     2345     |     0       |        US             |            NA          |
|     2        |     2345     |     3       |        US             |            NA          |
|     3        |     4456     |     0       |        UK             |            EU          |
|     3        |     4456     |     5       |        UK             |            EU          |
|     4        |     4456     |     2       |        UK             |            EU          |
|     5        |     4456     |     2       |        UK             |            EU          |
|     6        |     1234     |     0       |        US             |            NA          |
|     7        |     6678     |     0       |        US             |            NA          |
|     8        |     9900     |     0       |        US             |            NA          |
|     9        |     3334     |     0       |        US             |            NA          |    
|     10       |     3334     |     4       |        US             |            NA          |

該數據庫用於保存所有已完成的購買。 對於每次購買,他來自的customerID ,國家和大陸都會被保存。 顧客還可以從一組6種情緒中評價他的購買情況。 (快樂,失望,......)他選擇的情感被保存為情感emotionID

所以現在我需要一個查詢來獲取具有百分比信息的特定emotionID客戶。 假設我查找了emotionID = 0這是我想得到的:

|- customerID -|- emotionPercent -|
|     1234     |        100       |     
|     6678     |        100       |     
|     9900     |        100       | 
|     2345     |        50        |     
|     3334     |        50        | 
|     4456     |        25        |    

我正在使用此查詢:

SELECT customers.customerID, Count( customers.emotionID ) / C.totalPeople * 100.0 AS emotionPercent 
FROM `customers` 
INNER JOIN 

    (SELECT customers.customerID, Count( customers.emotionID ) AS totalPeople
    FROM `customers` 
    GROUP BY customerID) C 

ON customers.customerID = C.customerID 
WHERE customers.emotionID = 0 
GROUP BY customers.customerID 
ORDER BY emotionPercent DESC 
LIMIT 0,6

我已經搜索了答案,但額外的百分比計算讓我失望。 我找到了一些解決方案,需要填充某種臨時表,但我無法使其工作。

問題是:現在,數據庫中有140,000個條目,此查詢大約需要27秒。 這可能是對的嗎? 使用SQL - Server會顯着提高速度嗎?

我沒有得到的是:要求世界上最幸福的國家快速閃電(0.4秒),但結構上與第一個查詢類似(27秒):

SELECT customers.customerCountryCode, Count( customers.emotionID ) / C.totalPeople * 100.0 AS emotionPercent 
FROM `customers` 
INNER JOIN 

    (SELECT customers.customerCountryCode, Count( customers.emotionID ) AS totalPeople
    FROM `customers` 
    GROUP BY customerCountryCode) C 

ON customers.customerCountryCode = C.customerCountryCode 
WHERE customers.emotionID = 0 
GROUP BY customers.customerCountryCode 
ORDER BY emotionPercent DESC 
LIMIT 0,6

當我將此示例中的INNER QueryGROUP BY更改為customerID ,查詢也將永遠占用。 所以這是由customerID分組導致問題。 但為什么?

customerCountryCode定義為varchar(2) customerID是一個int(11) 這是否會導致查詢性能的巨大差異? 是否有更合適的變量類型? customerID最多可包含8個號碼。

很多問題! 感謝閱讀和任何幫助!

首先,如果您認為數據庫中的條目會膨脹,或者您的條目很高且服務器速度很慢,恕我直言,您可能希望預處理數據並將其存儲到具有匯總結果的另一個數據庫,這樣,您就不必一遍又一遍地請求相同的過程。 另外,嘗試為您的應用使用緩存插件。 php或ehcache在j2ee上的memcache將是安全的賭注。

您的問題可能是您正在使用子查詢。 由於子查詢不使用也不設置索引,因此它們使用最慢的連接方法(即全表掃描)。 我沒有足夠的經驗來提供僅限SQL的解決方案,因此我建議您將查詢分解為兩個單獨的調用。

  1. 獲得每個客戶的平均情緒並選擇前6個,保存為哈希或對象。
  2. 通過WHERE custumerID IN (id1, id2, id3, etc)獲取這6個客戶

雖然這可能不是最漂亮的解決方案,但您可以避免使用無索引子查詢(以及非常慢的全表掃描)。

謝謝你的幫助!

來自mySQL論壇的人建議添加一些索引:

ALTER TABLE customers
  ADD KEY idx_country_emid (customerCountryCode, emotionID),
  ADD KEY idx_emid_custid (emotionID, customerID);

查詢時間從27秒降至0.1秒。 ;)

此外,對於內部查詢,您可以編寫

(SELECT customers.customerCountryCode, Count( * ) AS totalPeople
    FROM `customers` 
    GROUP BY customerCountryCode) C 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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