2011-03-01 99 views
1

我有一個表(logs)具有以下列(還有其他的,但這些都是重要的):MySQL的:日期範圍內優化記錄查詢

  • ID(PK,INT)
  • 時間戳(日期時間)(指數)
  • 持續時間(INT)

基本上這是用於啓動的時間和在時間結束的事件的記錄。這張表目前有幾十萬行。我預計它會增長到數百萬。在Duration

  • 結束時間(日期時間)(指數)

爲了計算結束時間我已經加入的秒數到:加快查詢的目的,我已經添加另一列和預先計算的值Timestamp字段。

現在我想要做的是運行一個查詢,其中結果計算開始(Timestamp)和結束時間(EndTime)落在特定時間點之外的行數。然後,我想要在大時間範圍內(例如一年)每秒運行一次查詢。我還想計算在特定時間點開始的行數,並在特定時間點結束。

我創建了以下查詢:

SELECT 
    `dates`.`date`, 
    COUNT(*) AS `total`, 
    SUM(IF(`dates`.`date`=`logs`.`Timestamp`, 1, 0)) AS `new`, 
    SUM(IF(`dates`.`date`=`logs`.`EndTime`, 1, 0)) AS `dropped` 
FROM 
    `logs`, 
    (SELECT 
     DATE_ADD("2010-04-13 09:45:00", INTERVAL `number` SECOND) AS `date` 
     FROM numbers LIMIT 120) AS dates 
WHERE dates.`date` BETWEEN `logs`.`Timestamp` AND `logs`.`EndTime` 
GROUP BY `dates`.`date`; 

注意,號碼錶是嚴格輕易列舉的日期範圍。這是一個表,其中包含一列number,幷包含值1,2,3,4,5等...

這給了我正是我在找什麼......一張有4列的表格:

  • 日期
  • 新(行即開始在這個時間點)(即啓動和當前的時間點之外年末總排)
  • 下降(行爲此在這時間點)

問題是,此查詢可能需要大量的時間來執行。要經過120秒(如查詢所示),大約需要10秒。我懷疑這個速度與我要得到它的速度一樣快,但我想我會問在這裏是否有人提出改進此查詢性能的任何想法。

任何建議將是最有幫助的。感謝您的時間。

編輯:我有索引時間戳和結束時間。

EXPLAIN我查詢的輸出:

"id";"select_type";"table";"type";"possible_keys";"key";"key_len";"ref";"rows";"Extra" 
"1";"PRIMARY";"<derived2>";"ALL";NULL;NULL;NULL;NULL;"120";"Using temporary; Using filesort" 
"1";"PRIMARY";"logs";"ALL";"Timestamp,EndTime";NULL;NULL;NULL;"296159";"Range checked for each record (index map: 0x6)" 
"2";"DERIVED";"numbers";"index";NULL;"PRIMARY";"4";NULL;"35546940";"Using index" 

當我運行我的日誌表分析,它說的狀態確定。

+0

你有什麼索引? '說明你的查詢的輸出是什麼?你有[分析](http://dev.mysql.com/doc/refman/5.1/en/analyze-table.html)'logs'表嗎? – outis 2011-03-01 22:44:25

+0

@outis,謝謝你的問題。我已將這些信息添加到我的帖子底部。 – Brad 2011-03-01 23:40:04

+0

分析更多的是它對查詢優化器如何使用索引的影響。現在我很好奇擴展查詢計劃是用於查詢的,特別是查看查詢是否以及如何重寫。你會在'EXPLAIN EXTENDED'查詢後發佈'SHOW WARNINGS'的結果嗎? – outis 2011-03-02 00:21:20

回答

4

請注意EXPLAIN輸出中logs表的連接類型爲「ALL」且鍵爲NULL,這意味着將安排全表掃描。 「範圍檢查每個記錄」消息意味着MySQL在logs使用range access method的結果從別的地方檢查列值之後。我認爲這意味着,一旦dates已經創建,MySQL能夠執行遠程使用第二和第三個指標(可能是那些在TimestampEndTime),而不是執行全表掃描上logs加入。如果你只對TimestampEndTime指數分別,嘗試添加兩個指標,這可能會導致更有效的連接類型(例如index_merge而不是range):

CREATE INDEX `start_end` ON `logs` (`Timestamp`, `EndTime`); 

我相信(雖然很容易被錯)查詢計劃中的其他項目或者不是真正的問題或不能被消除。 filesort,作爲後者的一個例子,可能是由於GROUP BY。換句話說,這可能是您可以對此特定查詢執行什麼操作的程度,儘管針對表格存儲格式的完全不同的查詢或方法仍可能更有效。

+0

謝謝@outis,這是最有幫助的。我對優化查詢不太熟悉,這給了我很多繼續。我會對你的建議做更多的研究。與此同時,我想到了一個更有效的方法來做到這一點,將「日誌」限制爲相關條目,並且一次完成整個過程1天。我將在以後每天在應用程序上分別運行這些查詢,並將數據插入表中供以後使用。我會盡快發佈我最後的結果,但我現在無法得到它。我認爲我的ISP關閉了我的服務器,呵呵。 – Brad 2011-03-02 00:51:24

+0

@Brad:如果你還沒有,請務必閱讀[查詢執行計劃(MySQL文檔http://dev.mysql.com/doc/refman/5.5/en/execution-plan-information.html )。我的回答是基於該部分的信息。 – outis 2011-03-02 01:13:39

2

你可以看看merge tables用來加快處理。通過合併表,由於表被拆分,索引更小,導致更快的讀取。另外,如果您有多個處理器,搜索可以並行進行,從而提高性能。