2013-06-03 49 views
0

我有一個表記錄的開始時間和感興趣的事件的結束時間:MySQL的:有效地轉化事件日誌,以時間序列

CREATE TABLE event_log (start_time DATETIME, end_time DATETIME); 
INSERT INTO event_log VALUES ("2013-06-03 09:00:00","2013-06-03 09:00:05"), ("2013-06-03 09:00:03","2013-06-03 09:00:07"), ("2013-06-03 09:00:10","2013-06-03 09:00:12"); 

+---------------------+---------------------+ 
| start_time   | end_time   | 
+---------------------+---------------------+ 
| 2013-06-03 09:00:00 | 2013-06-03 09:00:05 | 
| 2013-06-03 09:00:03 | 2013-06-03 09:00:07 | 
| 2013-06-03 09:00:10 | 2013-06-03 09:00:12 | 
+---------------------+---------------------+ 

我正在尋找一種方式來創建一個「時間序列」表,其中一列是時間索引,另一列是當時正在進行的事件的計數。我可以通過子查詢和生成器來完成:

SET @first_time := (SELECT MIN(start_time) FROM event_log); 
SET @last_time := (SELECT MAX(end_time) FROM event_log); 

CREATE OR REPLACE VIEW generator_16 
AS SELECT 0 n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL 
    SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL 
    SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL 
    SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL 
    SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL 
    SELECT 15; 

CREATE TABLE time_series (t DATETIME, event_count INT(11)) 
SELECT @first_time + INTERVAL n SECOND t, NULL AS event_count 
    FROM generator_16 
    WHERE @first_time + INTERVAL n SECOND <= @last_time; 

UPDATE time_series 
    SET event_count= (SELECT COUNT(*) FROM event_log 
    WHERE start_time<=t AND end_time>=t); 

+---------------------+-------------+ 
| t     | event_count | 
+---------------------+-------------+ 
| 2013-06-03 09:00:00 |   1 | 
| 2013-06-03 09:00:01 |   1 | 
| 2013-06-03 09:00:02 |   1 | 
| 2013-06-03 09:00:03 |   2 | 
| 2013-06-03 09:00:04 |   2 | 
| 2013-06-03 09:00:05 |   2 | 
| 2013-06-03 09:00:06 |   1 | 
| 2013-06-03 09:00:07 |   1 | 
| 2013-06-03 09:00:08 |   0 | 
| 2013-06-03 09:00:09 |   0 | 
| 2013-06-03 09:00:10 |   1 | 
| 2013-06-03 09:00:11 |   1 | 
| 2013-06-03 09:00:12 |   1 | 
+---------------------+-------------+ 

有沒有更高效的方法來做到這一點?這種方法每次索引都需要一個子查詢。例如,是否有一種方法可以實現,即每個「event_log」記錄需要一個子查詢?我真正的問題是500k時間索引條目和1k事件;它需要比我想要的時間長一些(大約90秒)。

「發電機」片段來自http://use-the-index-luke.com/blog/2011-07-30/mysql-row-generator。顯然,較大的發生器之一,如64k版本或1M版本,將需要更大的問題。

回答

0

唯一的變化發生在start_time和end_time。 所以,如果你是

select distinct start_time As time_point from event_log 
UNION 
select distinct end_time As time_point from event_log 

...這將讓你在你需要的快照所有的「點」。

如果您在臨時表(如TEMP_POINTS)中創建該參數,並且如果返回event_log,則應該可以計算每個「點」處的事件數。

CREATE TABLE NON_ZERO_POINTS (t DATETIME, event_count INT(11)) 
    select time_point, count(*) 
    from TEMP_POINTS 
    join event_log on time_point between start_time and end_time 
    group by time_point 

可能是值得創建於NON_ZERO_POINTS

然後索引,你可以在你的更新從而使用NON_ZERO_POINTS:

UPDATE time_series 
SET event_count= (SELECT event_count FROM NON_ZERO_POINTS 
WHERE t=time_point); 

另外,你需要更新time_series?如果不是,則可以在查詢中使用它:

select t, coalesce(event_count) 
from time_series 
left join FROM NON_ZERO_POINTS 
on t=time_point 
+0

目前爲止有意義。你對第二部分有什麼建議(填補缺失的時間點?)我想不出有什麼辦法可以做到這一點,它不像我原來的方法那麼困難(也就是說,對於每個缺失的時間點需要一個子查詢)。 – andrewtinka

+0

該部分是否需要處於非過程化SQL?如果沒有,循環播放結果併發送更多的行比進來將是要走的路。 如果它必須是非過程化的SQL,那麼TEMP_POINTS應該首先包含每個可能的點。 (例如,一個包含0到59的表可以交叉連接到它自己,以產生所有3600個可能的mm:ss可能性。 –

+0

它需要處於非過程化SQL中。我實現了您建議的「連接」方法這種方式可以隨時產生值(將其添加到您的答案中)雖然這種方法使用「join」而不是子查詢,但很不幸,這似乎並沒有加快速度。 「事件日誌」表,它仍然很慢 – andrewtinka