2017-08-30 37 views
1

我遇到了MySQL上的執行路徑的問題,導致查詢緩慢和不一致。這是一個全新的現象。我們還有其他的表格,它們的設置完全相同(儘可能接近你的設置),但是由於某種原因,現在創建新表格有這個緩慢/不一致的問題。MySql執行路徑突然變化很多,不一致和緩慢

我們使用InnoDB版本: 「mysql Ver 14.14 Distrib 5.6.31,for debian-linux-gnu」。數據庫存在於一個無用的盒子裏。

該行爲在另一臺計算機上重現,並在全新版本的流浪盒後重現。

正如我所說的,數據庫是在我的本地機器上的一個流浪箱裏,而且我的機器沒有承受重負載。

t1有大約1米行。 t2是一個新表格。

這是始終重新產生問題的最簡單的查詢:

SELECT 
    * 
FROM 
    redacted_t1 AS t1 
     JOIN 
    redacted_t2 AS t2 ON t1.a_column = t2.id 
WHERE 
t2.c_column != 'asdff' 
ORDER BY t1.b_column DESC; 

參見下面的執行路徑是緩慢(超過3秒)的一些例子

我在看到至少2個其他執行路徑(這也是緩慢的),但由於它很難重現(隨機?)我不能在這裏發佈它們。

有時,但不是經常,我不知道如何或爲什麼,下面的執行路徑發生:

這是非常快,0.00秒。有時在數據庫中有一個全新的版本(如在一個新的vagrant box中),並且在t1和t2上運行優化會產生這樣的結果。有時優化 什麼都不做。有時這種執行狀態是在沒有優化表的情況下實現請注意,與慢執行路徑相比,t1的「行」數量要低得多。 這與我運行「顯示狀態」時看到的一致。

CREATE TABLE `redacted_t2` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 

    -- redacted 

    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci 

CREATE TABLE `redacted_t1` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `a_column` int(11) DEFAULT NULL, 

    -- redacted 

    PRIMARY KEY (`id`), 

    -- redacted 

    KEY `redacted_t1_a_column` (`a_column`), 

    -- redacted 

    CONSTRAINT `fk_redacted_t1_2032420404` FOREIGN KEY (`a_column`) REFERENCES `redacted_t2` (`id`), 
) ENGINE=InnoDB AUTO_INCREMENT=redacted DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci 

所以,我有幾個問題:

1)爲什麼執行路徑,以便不一致,爲什麼我們從來沒有遇到過嗎?

2)我們該如何去解決這個問題,那麼應該採取0.00 s的查詢不會隨機取3 s?

任何想法,建議,解釋非常感謝,謝謝!

+0

您的屏幕截圖顯示與您的問題中的文本不同的查詢。 「b_column」('t2.b_column!='asdff')上的屏幕截圖過濾器,而「c_column」('t2.c_column!='asdff')上的文本過濾器。哪個是對的? – markusk

+0

好的。只要它來自t2表,哪一列是無關緊要的。 –

+0

我問的原因是要確保在過濾器中實際使用的列上有一個索引。由於您的問題中顯示的DDL不包含'b_column'或'c_column',因此我無法判斷查詢是否過濾索引列。 – markusk

回答

0

已解決。

顯然,優化器是...不是太好。如果優化器無法處理您的查詢,請使查詢稍微複雜一些。

所以我給ORDER BY添加了一列。這解決了一切。不理想,但由於某種原因,它的工作原理。

SELECT 
    * 
FROM 
    redacted_t1 AS t1 
     JOIN 
    redacted_t2 AS t2 ON t1.a_column = t2.id 
WHERE 
t2.c_column != 'asdff' 
ORDER BY t1.b_column, t2.id DESC; 
1

您可以嘗試運行EXPLAIN EXTENDED,然後是SHOW WARNINGS,以獲取有關查詢執行計劃的更多詳細信息。詳細信息請參見8.8.3 Extended EXPLAIN Output Format

您還可以嘗試在t1t2上運行ANALYZE TABLE以確保MySQL在選擇其執行計劃時使用更新的表統計信息。

redacted_t2.c_column上添加索引可能會有幫助,因爲您正在過濾該列。

EXPLAIN輸出,似乎MySQL有時不使用索引redacted_t1_a_column。您可以鼓勵或強制數據庫使用index hints的索引,例如USE INDEXFORCE INDEX

+0

顯示警告顯示沒有關注,只是代碼1003(我知道是使用EXPLAIN EXTENDED的代碼)。 ANALYZE TABLE在您執行OPTIMIZE TABLE時運行,請參閱我的原始問題=) 不幸的是,向redacted_t2.c_column添加索引不會有幫助。 –

+0

「SHOW WARNINGS」結果的'Message'列是否包含任何有趣的內容? – markusk

+0

它沒有。只是你的標準東西與選擇逃脫和重命名的列,一個連接,在哪裏和順序。我會發布它,但我無權這樣做。但對我來說看起來不錯。 –

0
SET innodb_stats_sample_pages = 30; 
ANALYZE TABLE t1; 
ANALYZE TABLE t2; 

然後看看它是否更一致。由於你運行的是5.6.6,因此統計數據應該是「持久的」。不要使用OPTIMIZE TABLE

移動的,以優化:

你真的需要所有從兩個表中的列(SELECT *)?它在優化和索引方面有所不同。你有沒有向我們展示所有相關指標?有沒有TEXTBLOB列?你需要取他們嗎?

表中百分之多少是t2.c_column != 'asdff'?如果它是一個很小的百分比,那麼你需要INDEX(c_column)

t2只有5排長?如果是這樣,索引,解釋計劃等,都不會有太大影響。

+0

請解釋如何解釋計劃和索引將不重要,如果t2的行只是5?那麼,我應該如何/在哪裏尋找問題? t2是一個新表,所以它是空的,有時我加起來多達300行,行爲是一樣的。 –

+0

'EXPLAIN'可能會也可能不會改變。查找5中的特定行:使用索引有一些使用索引的開銷;使用沒有索引有一些跳過其他4行的開銷。時間差可能是亞毫秒。 (而且我無法預測哪個更快。)對於300行,索引變體可能會更快。故事的道德:從小桌子推斷演奏是危險的。 –