2012-08-03 100 views
4

我創造了電臺的報表生成在線聽衆的記錄,以IP,日期,時間,總用戶的記錄監聽等MySQL查詢優化加入

監聽器表

client_ip  date  time  date_time   listeners 
--------------- ---------- -------- ------------------- ----------- 
166.147.81.179 2012-04-30 00:19:46 2012-04-30 00:19:46   1 
64.12.243.203 2012-04-30 04:38:37 2012-04-30 04:38:37   1 
198.228.211.195 2012-04-30 05:36:33 2012-04-30 05:36:33   1 
198.228.211.195 2012-04-30 05:36:34 2012-04-30 05:36:34   2 
198.228.211.195 2012-04-30 05:36:35 2012-04-30 05:36:35   2 
198.228.211.195 2012-04-30 05:36:35 2012-04-30 05:36:35   3 
166.147.81.179 2012-04-30 05:47:13 2012-04-30 05:47:13   2 
76.170.251.97 2012-04-30 06:01:37 2012-04-30 06:01:37   2 
76.170.251.97 2012-04-30 06:01:39 2012-04-30 06:01:39   2 
76.170.251.97 2012-04-30 06:01:39 2012-04-30 06:01:39   2 

在它不斷的歌曲詳細信息(標題,藝術家,專輯,lenght,日期,時間)等

播放列表表

title      artist       length_in_secs played_date played_time start_date_time  end_date_time   
-------------------------- ------------------------------- -------------- ----------- ----------- ------------------- --------------------- 
We Found Love    Rihanna          184 2012-04-30 00:00:21  2012-04-30 00:00:21 2012-04-30 00:03:25 
Photograph     Nickelback         216 2012-04-30 00:03:31  2012-04-30 00:03:31 2012-04-30 00:07:07 
Not Over You    Gavin DeGraw        214 2012-04-30 00:07:18  2012-04-30 00:07:18 2012-04-30 00:10:52 
Stereo Hearts    Gym Class Heroes Ft Adam Levine    210 2012-04-30 00:10:55  2012-04-30 00:10:55 2012-04-30 00:14:25 
I Gotta Feeling    Black Eyed Peas       243 2012-04-30 00:15:03  2012-04-30 00:15:03 2012-04-30 00:19:06 
One Thing Leads To Another Fixx          182 2012-04-30 00:19:14  2012-04-30 00:19:14 2012-04-30 00:22:16 
Raise Your Glass   Pink          202 2012-04-30 00:22:29  2012-04-30 00:22:29 2012-04-30 00:25:51 
Better In Time    Leona Lewis         216 2012-04-30 00:30:13  2012-04-30 00:30:13 2012-04-30 00:33:49 
Tainted Love    Soft Cell         153 2012-04-30 00:33:56  2012-04-30 00:33:56 2012-04-30 00:36:29 
Haven't Met You Yet   Michael Buble'        242 2012-04-30 00:37:14  2012-04-30 00:37:14 2012-04-30 00:41:16 
記錄的同時,

因此,報告要求是「有多少用戶在日期或日期範圍內聽歌」,並且我寫這樣的查詢。它提供了正確的輸出(據我所知),但查詢執行需要時間與數據大小不成比例 - 從5秒到5-10分鐘,這取決於日期範圍。

SELECT DATE_FORMAT(p.played_date, "%m/%d/%Y") `played_date`, p.played_time, p.length_in_secs, p.title, p.artist, RTRIM(p.label) `label`, RTRIM(p.album) `album`, IFNULL((SELECT SUM(l.listeners) FROM listeners `l` WHERE l.date_time >= p.start_date_time AND l.date_time <= p.end_date_time LIMIT 1), 0) `listeners` FROM playlists `p` WHERE p.title <> "" AND (p.played_date >= '2012-04-30' AND p.played_date <= '2012-05-30') HAVING listeners > 0 ORDER BY p.title ASC; 
// formatted // 
SELECT 
    DATE_FORMAT(p.played_date, "%m/%d/%Y") `played_date`, 
    p.played_time, 
    p.length_in_secs, 
    p.title, 
    p.artist, 
    RTRIM(p.label) `label`, 
    RTRIM(p.album) `album`, 
    IFNULL(
     (SELECT 
      SUM(l.listeners) 
     FROM 
      listeners `l` 
     WHERE l.date_time >= p.start_date_time 
      AND l.date_time <= p.end_date_time 
     LIMIT 1), 
     0 
    ) `listeners` 
FROM 
    playlists `p` 
WHERE p.title <> "" 
    AND (
     p.played_date >= '2012-04-30' 
     AND p.played_date <= '2012-05-30' 
    ) 
HAVING listeners > 0 
ORDER BY p.title ASC 

輸出:

played_date played_time length_in_secs title     artist     label    album    listeners 
----------- ----------- -------------- --------------------- ------------------------ ------------------ ------------------ ----------- 
04/30/2012 08:06:26    228 Brighter Than The Sun Colbie Caillat (Cal-Lay) Universal Republic All of You     9 

04/30/2012 08:44:16    248 Breakfast At Tiffanys Deep Blue Something               6 

04/30/2012 18:06:40    253 Bizarre Love Triangle New Order                 2 

04/30/2012 17:05:21    183 Animal     Neon Trees    Mercury    Habits      5 

04/30/2012 08:58:05    253 Always Be My Baby  Mariah Carey                2 

04/30/2012 07:25:52    264 Already Gone   Kelly Clarkson   RCA     All I Ever Wante    3 

04/30/2012 16:21:33    236 All The Right Moves One Republic    Interscope   Waking Up      7 

04/30/2012 11:58:26    199 All That She Wants  Ace Of Base                12 

04/30/2012 11:14:17    247 All I Wanna Do   Sheryl Crow                 2 

04/30/2012 16:12:59    235 A Thousand Miles  Vanessa Carlton                5 

有沒有辦法來優化這個查詢運行得更快,或者寫一個新的,更快的呢?請建議/幫助我。謝謝!!

使用EXPLAIN

EXPLAIN playlists; 


Field   Type    Null Key  Default   Extra       
--------------- ---------------- ------ ------ ----------------- ----------------------------- 
playlist_id  int(10) unsigned NO  PRI  (NULL)    auto_increment    
title   varchar(255)  YES    (NULL)           
artist   varchar(255)  YES    (NULL)           
label   varchar(255)  YES    (NULL)           
album   varchar(255)  YES    (NULL)           
length_in_secs int(11)   NO    (NULL)           
played_date  date    NO    (NULL)           
played_time  time    NO    (NULL)           
start_date_time datetime   NO    (NULL)           
end_date_time datetime   NO    (NULL)           
added_date  datetime   NO    (NULL)           
modified_date timestamp   NO    CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP 


EXPLAIN listeners; 


Field   Type     Null Key  Default   Extra       
------------- ------------------- ------ ------ ----------------- ----------------------------- 
listener_id bigint(20) unsigned NO  PRI  (NULL)    auto_increment    
station_id  int(10) unsigned  NO    (NULL)           
client_ip  varchar(50)   NO    (NULL)           
time   time     NO    (NULL)           
date   date     NO    (NULL)           
date_time  datetime    YES    (NULL)           
timestamp  bigint(20) unsigned NO    (NULL)           
listeners  int(10) unsigned  NO    (NULL)           
processes  int(10) unsigned  NO    (NULL)           
uid   int(10) unsigned  NO    (NULL)           
user_agent  varchar(255)   YES    (NULL)           
added_date  datetime    NO    (NULL)           
modified_date timestamp   NO    CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP 
+0

你可以對其中一個需要更長時間執行的查詢運行'EXPLAIN'查詢嗎?也許問題在於,你正在運行的查詢沒有適當的索引,創建一個好的索引可以解決時間問題。此外,如果您可以顯示該表上當前的索引是非常有用的。謝謝 – drew010 2012-08-03 21:15:30

+3

如何識別用戶何時停止收聽? – invertedSpear 2012-08-03 21:32:20

+0

@invertedSpear,爲什麼需要停止/啓動,我需要上面的查詢優化就是這樣。 – 2012-08-04 03:06:10

回答

1

正如在評論中討論,您的查詢實際上並沒有做你想要做的事。鑑於您擁有的數據,我將親自處理SQL以外的這些數據,以創建一張表來存儲每首歌曲收聽的人數,然後您可以使用SQL查詢以獲取此信息。但是,如果你絕對想要一個SQL查詢來做到這一點,它將需要沿着這個怪物的行列;

SELECT 
DATE_FORMAT(p.played_date, "%m/%d/%Y") `played_date`, 
p.played_time, 
p.length_in_secs, 
p.title, 
p.artist, 
RTRIM(p.label) `label`, 
RTRIM(p.album) `album`, 
SUM(SMALLEST(prev_listeners,next_listeners,dur_listeners) AS listeners 
FROM (
    SELECT 
    P.start_date_time, 
    SUBSTRING_INDEX(GROUP_CONCAT(l_before.listeners ORDER BY l_before.date_time DESC),',',1) AS prev_listeners, 
    SUBSTRING_INDEX(GROUP_CONCAT(l_after.listeners ORDER BY l_after.date_time ASC),',',1) AS next_listeners, 
    MIN(l_during) AS dur_listeners 
    FROM playlists p 
    JOIN listeners l_before ON l_before.date_time < p.start_date_time 
    LEFT JOIN listeners l_after ON l_before.client_ip = l_after.client_ip AND l_after.date_time > p.end_date_time 
    LEFT JOIN listeners l_during ON l.client_ip = l_during.client_ip AND l_during.date_time BETWEEN p.start_date_time AND p.end_date_time 
    WHERE p.title <> "" 
    AND p.played_date BETWEEN '2012-04-30' AND '2012-05-30' 
    GROUP BY p.start_date_time, l_before.client_ip 
) l 
JOIN playlists p USING (start_date_time) 
GROUP BY p.start_date_time 
ORDER BY p.start_date_time 

其中SMALLEST是返回最小的non_null參數的函數。

這將花費比您當前的查詢長得多的時間,但這是我可以想到的用於獲取每首歌曲的實際聽衆數量的最有效方式。

哦,這是假設日誌記錄一個零聽衆的行,當每個人從一個IP地址停止監聽,否則真的沒有辦法做到這一點。

+0

接受,只是爲了邏輯,但沒有解決。謝謝!! – 2012-08-09 14:46:22

4

使用INNER JOIN而不是使用correlated subquery爲:

SELECT DATE_FORMAT(p.played_date, "%m/%d/%Y") played_date, 
     p.played_time, 
     p.length_in_secs, 
     p.title, 
     p.artist, 
     RTRIM(p.label) label, 
     RTRIM(p.album) album, 
     SUM(l.listeners) listeners 
FROM playlists p 
    INNER JOIN listeners l 
     ON l.date_time BETWEEN p.start_date_time AND p.end_date_time 
WHERE p.title <> "" AND 
     p.played_date BETWEEN '2012-04-30' AND '2012-05-30' 
ORDER BY p.title ASC; 

考慮表上添加以下索引可以幫助你提高查詢性能。檢查以下指標與EXPLAIN

playlists KEY (played_date, start_date_time, end_date_time, title); 

listeners KEY (date_time, listeners); 
+0

雖然差別在於隨着時間的推移而結束,但MySQL通常更快速,而使用'JOIN'而不是'SELECT'子類。 – staticsan 2012-08-06 07:09:17

+0

@Omesh沒有得到所需的結果。我粘貼上面,應該怎麼輸出。 – 2012-08-07 05:39:01

+1

我已經測試過它,它給出了與查詢相同的結果。您的輸出對於您提供的輸入數據看起來不正確。你可以爲它設置sqlfiddle嗎? – Omesh 2012-08-07 05:49:45