Index

我怎樣才能加快這個查詢?

  • October 21, 2018

以下是相關表的定義:

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 ontimestamp有用。

隨著這種變化的發生,兩者的組合索引在timestamp這裡region可能最有幫助。也許還添加price到最後,然後執行的查詢將不需要單獨的查找來在其他列過濾後找到該列(儘管這會增加索引的大小,因此您可能只為少量的速度交易空間)。

SELECT MAX(price) AS price 
 FROM pricehistory 
 WHERE timestamp > DATE_SUB(NOW(), INTERVAL 1000 DAY)
   AND region='us';

應該減少獲取此結果所需的 cpu。區域和時間戳(或時間戳和區域)的組合索引可能會加快速度。

引用自:https://dba.stackexchange.com/questions/220481