[英]Optimizing a SQL query to avoid full table scan
請考慮以下查詢:
SELECT * FROM Transactions
WHERE day(Stamp - interval 3 hour) = 1;
Transactions表中的Stamp列是TIMESTAMP,並且有一個索引。 我怎樣才能更改此查詢以避免全表掃描? (即在day()函數之外使用Stamp )
謝謝!
我就是這樣做的:
添加一些額外的字段:YEAR,MONTH,DAY甚至HOUR,MINUTE,具體取決於您期望的流量。 然后構建一個觸發器來填充額外的字段,可以提前減去3小時的間隔。 最后在額外字段上構建一些索引。
如果目標只是為了避免全表掃描並且您有一個PRIMARY KEY(比如命名為PK),請考慮添加覆蓋索引
ALTER TABLE Transactions ADD INDEX cover_1 (PK, Stamp)
然后
SELECT * FROM Transactions WHERE PK IN (SELECT PK FROM Transactions
WHERE day(Stamp - interval 3 hour) = 1
)
此查詢不應使用全表掃描(但是,如果表中的行數很小或者出於其他任何統計原因,優化程序可能決定使用完全掃描:))
更好的方法可能是使用臨時表而不是子查詢。
你經常可以重寫這個函數,所以你有一些看起來像WHERE Stamp=XXXX
和XXXX的東西。 您可以為每個月創建一系列BETWEEN語句, WHERE Stamp BETWEEN timestamp('2010-01-01 00:00:00') AND timestamp ('2010-01-01 23:59:59') OR Stamp BETWEEN ...
,但我不確定在這種情況下會使用索引。 我建立了一個專欄,就像@petr建議的那樣。
在運行主查詢之前單獨計算所需的Stamp值,即
第1步 - 計算所需的Stamp值
第2步 - 運行查詢,其中Stamp>(計算值)
由於步驟2中沒有計算,您應該能夠使用索引。
如果我理解正確的話,你基本上想要返回每個月郵票落在第一行的所有行(減去3小時)? 如果(這是一個很大的if),你有一個固定的窗口,比如說最近的6個月,你可以枚舉6個范圍測試。 但是,我仍然不確定索引訪問會更快。
select *
from transactions
where stamp between timestamp '2010-06-01 03:00:00' and timestamp '2010-06-02 02:59:59'
or stamp between timestamp '2010-07-01 03:00:00' and timestamp '2010-07-02 02:59:59'
or stamp between timestamp '2010-08-01 03:00:00' and timestamp '2010-08-02 02:59:59'
or stamp between timestamp '2010-09-01 03:00:00' and timestamp '2010-09-02 02:59:59'
or stamp between timestamp '2010-10-01 03:00:00' and timestamp '2010-10-02 02:59:59'
or stamp between timestamp '2010-11-01 03:00:00' and timestamp '2010-11-02 02:59:59'
or stamp between timestamp '2010-12-01 03:00:00' and timestamp '2010-12-02 02:59:59';
NB! 我不確定時間戳的毫秒部分是如何工作的。 您可能需要相應地填充它。
重新設計petr的答案以避免使用IN子句,並將其用於MyISAM或InnoDB。
對於MyISAM
ALTER TABLE Transactions ADD INDEX cover_1 (PK, Stamp)
或者,對於InnoDB,PK隱含地包含在每個索引中,
ALTER TABLE Transactions ADD INDEX Stamp (Stamp)
然后
SELECT *
FROM Transactions LEFT JOIN
(
SELECT PK
FROM Transactions
WHERE DAYOFMONTH(Stamp - interval 3 hour) = 1
) a ON Transactions.PK=a.PK
子查詢將僅執行索引,外部查詢將僅從a.PK通過的表中提取行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.