2017-09-05 39 views
2

我有MariaDB的10.1.14,很長一段時間我做沒有問題下面的查詢(它tooks約3秒):查詢時間突然增加

SELECT 
    sum(transaction_total) as sum_total, 
    count(*) as count_all, 
    transaction_currency 
FROM 
    transactions 
WHERE 
    DATE(transactions.created_at) = DATE(CURRENT_DATE) 
    AND transaction_type = 1 
    AND transaction_status = 2 
GROUP BY 
    transaction_currency 

突然間,我不知道到底爲什麼這個查詢需要大約13秒。
這是EXPLAIN: enter image description here

而這些都是交易表的所有索引: enter image description here

什麼是突如其來的查詢時間增加的原因?我該如何減少它?

+0

日期funtion在transactions.created_at是需要時間mysql不會使用索引如果列中包含函數 –

+1

我會說有些事情已經改變了。那麼你改變了什麼? – RiggsFolly

+0

@RiggsFolly我想到了這一點,但MAYBE唯一改變的地方是,如果AWS升級Maria次要版本,但它看起來不像它的更新。 – Michael

回答

1

+1從@JuanCarlosOropeza回答,但你可以去索引稍微進一步。

ALTER TABLE transactions ADD INDEX (
    transaction_type, 
    transaction_status, 
    created_at, 
    transaction_currency, 
    transaction_total 
); 

As @RickJames在評論中提到,列的順序很重要。

  • 首先,列相等比較
  • 接下來,可以說被用於範圍比較(這是除了任何平等)索引一個列或GROUP BY或ORDER BY。你有範圍比較和GROUP BY,但你只能得到索引來幫助其中的一個。
  • 最後,查詢所需的其他列,如果您認爲可以獲得覆蓋索引。

我在我的演示文稿How to Design Indexes, Really(視頻:https://www.youtube.com/watch?v=ELR7-RdU9XU)中介紹了有關索引設計的更多詳細信息。

由於您有一個範圍條件,並且還有一個GROUP BY引用了不同的列,所以您可能會陷入「使用臨時」狀態。但你至少可以通過這一招消除「使用文件排序」。

... 
GROUP BY 
    transaction_currency 
ORDER BY NULL 

假設,這不是對你很重要,其訂購查詢結果的行中返回

+0

非常感謝!索引實際上有幫助(不到一秒!!!),但是..這不是太具體的索引?我試圖爲每一列創建索引,但它給了我一點點改進,同樣,爲什麼這個查詢需要這麼長時間?並感謝偉大的幻燈片和視頻! – Michael

+0

這是常見的/確定只爲一個查詢創建索引? – Michael

+1

@Michael通常情況下,答案是肯定的,因爲您希望提高響應時間,但取決於查詢。請記住,創建索引佔用空間並影響該表上的插入和更新。這是一種折衷。由你決定是否值得。硬盤空間非常便宜,所以不是真正的問題。 –

4

如果您要向表中添加更多數據,查詢時間將會增加。

但是你可以做一些事情來提高性能。

  • 創建(transaction_type, transaction_status, created_at)
  • 從您的領域DATE()功能(或功能)的綜合指數,因爲不允許引擎使用索引。 CURRENT_DATE是一個常數所以無所謂,但沒有必要,因爲已經返回DATE
    • 如果created_at心不是日期可以使用
    • created_at >= CURRENT_DATE and created_at < CURRENT_DATE + 1
    • 或創建一個不同的領域僅保存日期部分。
+0

你的答案在DATE()比我的問題更明確。很好解釋。 –

+0

但指數倒退。 「範圍」部分('created_at')需要是最後一個。 –

+0

@RickJames你確定嗎?看起來沒問題。你會建議什麼? –

0

我不知道是什麼使您的查詢慢。更多數據?不成?新的數據庫版本?

但是,我很驚訝地發現沒有真正支持查詢的索引。您應該有一個以最高基數的列開始的複合索引(日期?那麼您可以嘗試不同的列順序並查看DBMS爲查詢選擇哪個索引)。

create index idx1 on transactions(created_at, transaction_type, transaction_status); 

如果created_at包含日期的一部分,那麼你可能要創建一個計算列created_on只包含日期和索引來代替。

您可以將這個指標甚至擴展到覆蓋索引(其中後面組子句領域by子句場其後SELECT子句字段):

create index idx2 on transactions(created_at, transaction_type, transaction_status, 
            transaction_currency, transaction_total);