2017-04-22 112 views
0

在350萬條記錄的表,其結構是:哪個索引會加快查詢速度?

CREATE TABLE `table` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `job_id` int(10) unsigned NOT NULL, 
    `lock` mediumint(6) unsigned DEFAULT '0', 
    `time` timestamp NULL DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `job_id` (`job_id`), 
    KEY `lock` (`lock`), 
    KEY `time` (`time`) 
) ENGINE=MyISAM; 

我應該創建什麼索引來加快查詢:

UPDATE `table` SET `lock` = 1 WHERE `lock` = 0 ORDER BY `time` ASC LIMIT 500; 
+0

爲什麼使用MyISAM?如果你經常運行這個查詢,MyISAM只有一個表鎖。這意味着當這個查詢(或其他一些寫入)運行其他人可以讀取或寫入這個表 –

+0

@BerndBuffen,你建議使用什麼? – Dmitry

+0

請不要使用不相關的數據庫標籤。 –

回答

0

對於此查詢:

UPDATE `table` 
    SET `lock` = 1 
    WHERE `lock` = 0 
    ORDER BY `time` ASC 
    LIMIT 500; 

最好的指數是table(lock, time)。但請注意,更新還需要更新索引,因此您應該測試它在實際中的工作情況。不要把它作爲聚集索引。這隻會減緩這一進程。

+0

這個密鑰的工作時間很長。這似乎是由於請求導致更新相同索引的事實。 – Dmitry

1

lock被宣佈爲NULLable。這是否意味着價值往往是NULL?如果是這樣,那麼在MyISAM(而不是InnoDB)中存在一個令人討厭的問題,可能會導致500次額外的碎片命中。

當MyISAM行更新它變得更長,那麼該行將不再適合它的位置。 (現在我的詳細知識變得模糊了。)新的行將被放置在其他地方,並且/或者它將被分成兩部分,並且部分之間有鏈接。這意味着寫在兩個地方。

戈登指出,任何改變你的情況下,任何索引列,lock,涉及昂貴的索引更新 - 從一個地方索引的B樹中刪除「行」,並在另一個地方添加一行。

lock只有值0或1?然後使用TINYINT(1字節),而不是MEDIUMINT(3字節)。您需要檢查MAX(id)。如果它是乾淨的,id的最大值將是大約350M(不太接近4B的限制)。但如果有任何流失,它可能會更接近極限。

我也提倡切換到InnoDB。但是,您的10GB(數據+索引)在轉換中將增長到20-30GB。

你是否「鎖定最古老的解鎖」thingies?你會做一個選擇,看看什麼被鎖定?

如果這太慢,一次不要做500,選擇一個較低的數字。

有了InnoDB,你可以避免鎖定嗎? 也許事務鎖定就足夠了?

我認爲我們需要看看環境的其他部分 - 其他表格,工作「流動」等。我們可能會提出其他建議。

而我第二個動議爲INDEX(lock, time)。但是這樣做的時候,DROP這個索引就是lock那樣多餘。

而當轉換爲InnoDB時,請在同一個ALTER中執行所有索引更改。這將比單獨的傳球跑得快。

+0

感謝您的回答,我嘗試將錶轉移到InnoDB並執行sql查詢的測試。 – Dmitry