2010-06-24 60 views
0

我有兩個表:一個有日期時間列,另一個有日期列。優化加入DATE的SQL查詢(datetime)= date?

我要加入兩個表是這樣的:

SELECT 
    t1.dt, 
    t2.d 
FROM 
    table1 t1, 
JOIN 
    table2 t2 
ON 
    DATE(t1.dt) = t2.date 

但很明顯,這可以殺死t1.dt索引。

解決此問題的最佳策略是什麼?最簡單的方法是添加一個新列到t1(並將其設置爲date(t1.dt)),但我不喜歡重複數據的想法。

有沒有一個很好的方法來解決這個問題?

回答

1

您的日期時間列由日期和時間部分組成。由於您希望單獨爲日期部分編制索引,因此將日期時間列分爲兩個單獨列(一個用於時間部分,另一個用於日期部分)是有意義的。然後可以對日期列編制索引,並可以在查詢中使用索引。採用這種方法,您根本不會複製任何數據。

0

我並不確定,但是這可能會迫使MySQL在日期時間減去日期時迭代所有行。你應該使用EXPLAIN來確保。你可以做這樣的事情解決這個問題:

(t1.dt >= "2010-06-24 00:00:00" 
    AND t1.dt < ("2010-06-24 00:00:00" + INTERVAL 1 DAY)) 

編輯:只是使用日期()試過了,似乎MySQL的仍然使用索引:

CREATE TEMPORARY TABLE t1 (
    dt DATETIME, 
    INDEX iDt (dt) 
); 

INSERT INTO t1 VALUES 
    (NOW()), 
    (NOW() - INTERVAL 1 DAY), 
    (NOW() - INTERVAL 1 DAY), 
    (NOW() - INTERVAL 2 DAY); 

CREATE TEMPORARY TABLE t2 (
    dt DATETIME, 
    INDEX iDt (dt) 
); 

INSERT INTO t2 VALUES 
    (NOW()), 
    (NOW() - INTERVAL 1 DAY), 
    (NOW() - INTERVAL 1 DAY), 
    (NOW() - INTERVAL 2 DAY); 

# t1: Using index. t2: Using where+index 
EXPLAIN EXTENDED 
SELECT 
    * 
FROM t1 
    JOIN t2 ON DATE(t1.dt) = DATE(t2.dt) 
+0

我試過類似的:'ON t1.td BETWEEN t2.date AND t2.date + INTERVAL 1 DAY',它使它快一點,但後半部分BETWEEN沒有索引,所以它仍然使用filesort和臨時的。 – aidan 2010-06-24 10:38:44

+0

你可以給一個解釋擴展,看看它說什麼? – simendsjo 2010-06-24 12:19:28

0

試試這個。這將使索引使用

SELECT 
    t1.dt, 
    t2.d 
FROM 
    table1 t1, 
JOIN 
    table2 t2 
ON 
    t1.dt>=t2.date and 
    t1.dt <(t2.date + INTERVAL 1 DAY) 
+0

似乎沒有這樣做。它可能會查詢掛起。 – transilvlad 2014-03-02 12:24:39