2017-08-15 52 views
1

我的下一個InnoDB表:Mysql的不正確的優化器的工作

CREATE TABLE events (
    id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, 
    server int(11) UNSIGNED NOT NULL, 
    internal_id bigint(20) UNSIGNED NOT NULL, 
    pid int(11) UNSIGNED NOT NULL, 
    event_datetime DATETIME NOT NULL, 
    event_stamp int(11) NOT NULL, 
    status tinyint(3) UNSIGNED NOT NULL DEFAULT 1, 
    PRIMARY KEY (id), 
    INDEX IDX_events (event_stamp, pid), 
    INDEX IDX_events2 (event_stamp), 
    UNIQUE INDEX UK_events_hash (internal_id, server) 
) 
ENGINE = INNODB; 

中的記錄數爲〜5百萬。當我執行下一個SQL時:

EXPLAIN SELECT SQL_NO_CACHE id, internal_id, pid, status FROM events WHERE event_stamp BETWEEN UNIX_TIMESTAMP('2017-01-01') AND UNIX_TIMESTAMP(CURDATE()); 

Profiler說有2個可能的索引,但沒有一個被使用。總執行時間爲0.105毫秒。然後我添加「FORCE INDEX (IDX_events2)」,Profiler說使用索引,總執行時間爲0.02毫秒。

那麼爲什麼優化器會認爲不使用索引並且通過~2百萬條記錄比使用索引更快?以更快的速度執行索引,這是合乎邏輯的。

Explain輸出:
1 SIMPLE c (null) ALL IDX_events,IDX_events2 (null) (null) (null) 5944539 50 Using where

,並與力:
1 SIMPLE c (null) range IDX_events2 IDX_events2 4 (null) 2972269 100 Using index condition

+0

除非我誤解:0.105ms大於0.020ms。 – RToyo

+0

是的,我不明白爲什麼優化器不使用索引。隨着力量指數它更快 – hadwin

+0

提供我們的力量和沒有力量的解釋 – Noob

回答

2

最數據庫採用B樹索引。在這種情況下,數據庫優化器不使用索引,因爲它更快地掃描沒有索引

2mil/5mil> 20%,我猜這是更快的做表掃描,然後使用索引。指數並不總是最好的解決辦法Avoid full table scan

從EXPLAIN顯示了所有的類型列時,MySQL使用一個 全表掃描來解決查詢的輸出。這通常是 下列情況下發生:

您正在使用低基數的關鍵通過另一列(許多行的關鍵 值相匹配)。在這種情況下,MySQL假定通過使用密鑰 它可能會執行許多密鑰查找,並且表 掃描會更快。

在您的查詢使用範圍運算符。在大多數情況下,它更快地避免索引掃描。當您創建索引時,掃描索引頁面進行匹配會花費更多。

+0

是的,我明白了。但真正的執行表明,強制使用索引要快得多(沒有索引的情況下爲105毫秒,強制的情況下爲20毫秒 - 快了400%)。所以我不明白爲什麼優化器認爲表掃描速度更快 – hadwin