[英]Same query, different execution plan with limit and sort by. Should I change the index?
我有一個包含 1,000,000 條記錄的表。 表看起來像這樣:
CREATE TABLE `items` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`category_id` int(10) unsigned NOT NULL,
`item_serial` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_index` (`category_id`,`item_serial`),
)
當我執行此查詢時:
select * from `items`
where `category_id` = 1
order by `id` asc
limit 22649;
大約需要 0.5 秒,我發現這很長。
如果我執行查詢的解釋,我會得到以下結果:
type | possible_keys | key | key_len | ref | rows | filtered | Extra
-----|----------------|----------------|---------|-------|-------|----------|-----------------------------------------
ref | unique_index | unique_index | 4 | const | 498253| 100.00 | Using where; Using index; Using filesort
如果我執行完全相同的查詢,但只是從限制中刪除 1 位數字,那么 22648 而不是 22649:
select * from `items`
where `category_id` = 1
order by `id` asc
limit 22648;
查詢持續時間要快得多,大約 0.003 秒。
我得到以下結果進行解釋:
type | possible_keys | key | key_len | ref | rows | filtered | Extra
-----|----------------|----------------|---------|-------|-------|----------|-------------
ref | unique_index | PRIMARY | 8 | null | 45296| 50.00 | Using where
如您所見,兩個查詢的解釋各不相同,並且查詢持續時間也大不相同。
我還使用了 unique_index 並將 id 列添加到該索引中,將其更改為:
UNIQUE KEY `unique_index` (`id`, `category_id`, `item_serial`),
當我這樣做時,我不再得到不同的結果,但總是使用新索引得到相同的解釋結果,並且快速結果約為 0.003 秒。
所以我有兩個問題:
1 - 為什么具有不同限制的相同查詢會產生不同的執行計划?
2 - 您是否建議將 id 列添加到 unique_index 以獲得更好的性能? 我覺得添加它很奇怪,因為它在唯一性方面沒有意義,因為 id 是自動遞增的並且永遠不會重復,但它確實解決了這種情況下的性能問題。
將不勝感激任何建議。
你發現了一個優化器被撕裂的情況
category
過濾 -- 覆蓋索引,但需要排序id
順序讀取排序,但必須檢查每一行。碰巧優化器的硬幣翻轉正好是 22649。明天可能會有所不同——更大或更小。
將1
(對於category_id
)更改為表中的最大值; 時機可能真的很糟糕。
如前所述,以這兩列開頭的索引是最佳的:
INDEX(category_id, id)
注意:InnoDB 將PRIMARY KEY
列添加到每個二級索引的末尾。 實際上,該表是兩個 BTree:
(id, category_id, item_serial) -- All the data, in PK order
(category_id, item_serial, id) -- secondary index plus PK
重新 0.003 秒。 -- 這聞起來像是查詢緩存被打開了。 它具有欺騙性。 建議使用SELECT SQL_NO_CACHE ...
重新計時SELECT SQL_NO_CACHE ...
你應該改變索引嗎? 好,
UNIQUE KEY `unique_index` (`category_id`,`item_serial`)
既是索引又是唯一性約束。 如果您更改此設置,您將失去唯一性約束。 所以,你堅持添加
INDEX(category_id, id)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.