2017-02-10 26 views
0

我要解釋一下,像這樣的查詢量:(POST_ID = PRIMARY,blog_id =指數)SQL提高效率:限制文件排序

SELECT post_id FROM posts WHERE blog_id IN (2,3,...) ORDER BY post_id DESC LIMIT 10 

更新:在了IDS()可能很多。 如果DB使用blog_id關鍵的查詢,它使一個文件排序,因爲該指數是這樣的:

(blog_id,post_id)-> (1,55) (1,59) (1,69) (2,57) (2,71) (2,72) (3,12) 

的相反,如果IN()您搜索只是一個ID blog_id = 2,它不需要執行任何文件,因爲所有的匹配都已經完成。

我認爲這是發生的問題,而不是100%確定,但僅僅通過查看查詢執行時間,是因爲如果我添加一個LIMIT 10,有效的方法是隻捕獲每個文件的最後10個ID blog_id索引鍵匹配,也許它已經這樣做了,但看起來像一個IN(2,3,4)ORDER BY post_id DESC LIMIT 10,它將filesids成千上萬的id而不是30.

我希望我只是死了錯,因爲如果我不是那是一個可怕的低效率的錯誤。 如果我是對的,是否有任何引擎或改變我可以做?甚至改變數據庫。目前我在10.1.13-MariaDB上,表是InnoDB

+0

你真的在做'SELECT post_id',而不是'SELECT *'嗎?這對_this_問題有重大影響。 –

+0

是的,因爲它是一個更大的子查詢,我選擇*並加入到其他表中,並且在一年前的一個問題中已經有人告訴我這種形式更有效。 http://stackoverflow.com/questions/30414641/avoid-filesort-with-inner-join-order-by – Vixxs

回答

2

不幸的是,MySQL沒有一個索引可以讓你做你想做的事。

但是你可以重寫你的查詢,並使用現有的索引:

SELECT p.post_id 
FROM ((SELECT post_id 
     FROM posts 
     WHERE blog_id = 2 
     ORDER BY post_id DESC 
     LIMIT 10 
    ) UNION ALL 
     (SELECT post_id 
     FROM posts 
     WHERE blog_id = 3 
     ORDER BY post_id DESC 
     LIMIT 10 
    ) 
    ) p 
ORDER BY post_id DESC 
LIMIT 10; 

每個子查詢將使用索引。而對20個元素的排序非常快。

+0

那麼,IN()ids可以是數百個,它們是動態的,它們會改變,這就是一個例子。從我的角度來看,我認爲我所說的會容易和技術上可行,所以我不明白爲什麼它沒有完成,在我的腦海中是沒有意義的。順便說一句,我現在與MariaDB有新的表引擎。沒有任何可能性? 你說有沒有這樣的索引,也許是錯誤的我對索引的順序的理解?因爲索引適合我,所以我在這裏看到的問題是引擎搜索的方式。 – Vixxs

+0

PD:由「他們是動態的,他們改變」我的意思是數量的變化,這可以被整理出來,但正如我所說可以有很多IDS。 – Vixxs

+1

'UNION'方法適用於少數blog_id;對於大數量(N)不太好,'UNION'的開銷加上tmp表格將是10 * N行。 –

1

看看EXPLAIN SELECT ...;看看它是否說「filesort」。

執行以下操作以獲取詳細信息,即使是小型數據集:

FLUSH STATUS; 
SELECT ...; 
SHOW SESSION STATUS LIKE 'Handler%'; 

你需要INDEX(blog_id, post_id)。如果你使用的是InnoDB,並且表格有

PRIMARY KEY(post_id), 
INDEX(blog_id) 

那麼你確實有這個組合索引。這是因爲每個二級索引都隱含包含PK的列。

由於您使用的是MariaDB,請參閱LIMIT ROWS EXAMINED是否會處理您詢問的其他問題。

當優化看到這一點:

WHERE blog_id IN (2,3) 
ORDER BY post_id DESC LIMIT 10 

和它既有INDEX(blog_id)INDEX(post_id),它使一個決定 - 但在有限的統計數據 - 以哪個方向走:

A計劃:在blog_id + filesort上過濾,或
B計劃:以post_id順序掃描,希望儘快找到10行。

兩者都有風險。如果大部分或全部行都是(2,3),則計劃A將具有很大的排序。規劃B,當少於10個匹配行時,將掃描整個表(或索引)。

+0

是的,我嘗試強制主要之前,並根據測試,根據帖子的數量,或者如果他們太深入索引,一種或其他方式表現更好,我將不得不通過看平均查詢。但我寧願不做出這樣的選擇,並找到一種方法去做我的問題所暗示的,我想在幾乎所有的疑問中,這兩種選擇都會勝過這兩種選擇。 LIMIT ROWS EXAMINED並不是爲此而設計的,如果數字太低,它會產生這個致命錯誤:#1028 - Sort aborted: – Vixxs

+0

然後我認爲您需要重新考慮「要求」。或者也許改變「用戶期望」。你能犧牲那個長長的名單嗎?訂購?還有別的嗎? (並非所有的性能問題都可以解決;你只是簡單地解釋一下,但很難解決問題。) –