Index
我怎樣才能加快這個查詢?
以下是相關表的定義:
CREATE TABLE IF NOT EXISTS pricehistory ( id INTEGER(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, price INTEGER NOT NULL, region VARCHAR(20) NOT NULL, timestamp TIMESTAMP NOT NULL, is_from_api INTEGER DEFAULT 0)
這是有問題的查詢:
SELECT MAX(price) AS price FROM pricehistory WHERE UNIX_TIMESTAMP(CONVERT_TZ(timestamp, '+00:00', 'SYSTEM')) > UNIX_TIMESTAMP(CONVERT_TZ(DATE_SUB(NOW(), INTERVAL 1000 DAY), '+00:00', 'SYSTEM')) AND region='us';
這裡是解釋
id: 1 select_type: SIMPLE table: pricehistory type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 368040 Extra: Using where
好的,所以這個查詢執行得很慢。我認為只執行300k-400k 行大約需要 500 毫秒。
大約 1/5 的行有一個 region=‘us’。如果我刪除 UNIX_TIMESTAMP() 函式,它會將執行時間減少大約 100 毫秒,所以我可能會這樣做。
我嘗試過索引,但我是索引新手,以前從未做過。我所做的所有索引要麼沒有效果,要麼進一步減慢了查詢速度。
我需要最後
x
幾天的最高價格,整個表中只有 1/5 的行(region=‘us’)。我想不出一種方法來建立一個索引。注意:我還有一個獲取最低價格的查詢。
伺服器版本:10.1.35-MariaDB - mariadb.org 二進制發行版。
因為您的
WHERE
子句引用timestamp
將列包裝在一個函式中,所以它不能有效地使用索引來可能目前正在掃描整個表。上的索引
region
可能會有所幫助,但除非該列非常有選擇性(或者如果大多數行來自您正在查看的區域,則根本沒有)。當您將相同的函式應用於列和您正在搜尋的值時,您可以刪除它:不等式
UNIX_TIMESTAMP(CONVERT_TZ(timestamp, '+00:00', 'SYSTEM')) > UNIX_TIMESTAMP(CONVERT_TZ(DATE_SUB(NOW(), INTERVAL 1000 DAY), '+00:00', 'SYSTEM'))
正好等價於
timestamp > DATE_SUB(NOW(), INTERVAL 1000 DAY)
這將允許 in index on
timestamp
有用。隨著這種變化的發生,兩者的組合索引在
timestamp
這裡region
可能最有幫助。也許還添加price
到最後,然後執行的查詢將不需要單獨的查找來在其他列過濾後找到該列(儘管這會增加索引的大小,因此您可能只為少量的速度交易空間)。
SELECT MAX(price) AS price FROM pricehistory WHERE timestamp > DATE_SUB(NOW(), INTERVAL 1000 DAY) AND region='us';
應該減少獲取此結果所需的 cpu。區域和時間戳(或時間戳和區域)的組合索引可能會加快速度。