2012-12-05 104 views
4

此查詢的執行時間超過2秒(對於10k行)。有沒有可能優化這個查詢?MySQL中BETWEEN的執行時間很長

SELECT id, MIN(ABS(timestamp_a - timestamp_b)) 
FROM a 
    INNER JOIN b ON (timestamp_a between (timestamp_b - 5 * 60) 
       AND (timestmap_b + 5 * 60)) 
GROUP BY id 

樣本結果(ID,timestamp_a,timestamp_b,差異):

1 1349878538 1349878539 1 
2 1349878679 1349878539 2 
3 1349878724 1349878539 1 
5 1349878836 1349878539 1 
6 1349878890 1349878641 1 

表一個

CREATE TABLE `a` (
`id` int(11) NOT NULL AUTO_INCREMENT , 
`timestamp_a` bigint(20) NULL DEFAULT NULL , 
PRIMARY KEY (`id`), 
INDEX `a` (`timestamp_a`) USING BTREE 
) 

表B

CREATE TABLE `b` (
`id` int(11) NOT NULL AUTO_INCREMENT , 
`timestamp_b` bigint(20) NULL DEFAULT NULL , 
PRIMARY KEY (`id`), 
INDEX `b` (`timestamp_b`) USING BTREE 
) 

兩個表之間沒有相關 - 我搜索表'a'中的記錄a在'b'表中的時間戳之間。

編輯:simples解決方案(運行速度非常快):

SELECT id, MIN(ABS(timestamp_a - timestamp_b)) 
FROM (SELECT id, timestamp, (timestamp - 5 * 60) timestamp_a, (timestamp + 5 * 60) timestamp_b) a 
INNER JOIN b ON (timestamp between timestamp_a AND timestamp_b) 
GROUP BY id 
+0

你能解釋一下你的表格結構嗎?可能包括您的問題中兩個表的「SHOW CREATE TABLE」輸出。這些表格如何相互關聯?我認爲主要問題是您的JOIN條件非常複雜,但如果沒有這些信息,很難推薦替代方案。 –

+0

thx爲你的答案 - 請現在看到我的問題 – ekstro

+0

它不會幫助這個查詢顯着,但你應該使時間戳列'TIMESTAMP's或'INT UNSIGNED NOT NULL'; 'BIGINT'只是錯誤的類型。 ID列也應該是'UNSIGNED'。 –

回答

0

以邁克爾的約定修改時間戳列,該查詢將產生原始查詢的預期結果與「更快的性能「上面的查詢:

SELECT a.id, MIN(ABS(a.timestamp_a - tmp_b.timestamp_b)) 
FROM (SELECT id, timestamp_b, (timestamp_b - 5 * 60) timestamp_b_minus, (timestamp_b + 5 * 60) timestamp_b_plus) tmp_b 
INNER JOIN a ON (a.timestamp_a between tmp_b.timestamp_b_minus AND tmp_b.timestamp_b_plus) 
GROUP BY a.id 

的原因,原來的查詢體驗性能限制是,RDBMS被強制執行的b全表掃描由於在ON子句中使用的公式,因此在a中的每一行。

即使「快」查詢需要的b全表掃描,生成「臨時」表tmp_b它能夠使用上a.timestamp_a索引來提取a基於標準的相應值:tmp_b。 timestamp_b_minus AND tmp_b.timestamp_b_plus