2011-12-27 20 views
2

時,Mysql查詢運行非常緩慢按以下查詢需要30秒才能完成訂購。沒有它的順序完成在0.0035秒。我已經有一個字段「名稱」的索引。字段「id」是主鍵。我在這張桌上有40萬張唱片。請幫助,使用order by時查詢出了什麼問題。當按順序使用

SELECT * 
FROM users 
WHERE name IS NOT NULL 
AND name != '' 
AND (status IS NULL OR status = '0') 
order by id desc 
limit 50 

更新:(末尾的解決方案) 大家好,感謝您的幫助。下面是你問的一些更新:

  1. 下面是解釋的輸出。

    ID SELECT_TYPE表型possible_keys鍵key_len REF行額外

    1 SIMPLE用戶範圍名稱名稱258 NULL 226009使用其中;使用filesort

  2. 是的,這個表中有大約20個字段。

  3. 下面是我的指標:

    鍵名類型基數字段

    PRIMARY PRIMARY 418099 ID 名INDEX 411049名

解決方案: 原來同場空值是原因。將where條件中的這兩個字段設置爲NOT NULL時,它只需要.000x秒。但奇怪的是,如果我創建(status,name,id DESC)或(status,name,id)索引,它會增加到29秒。

+0

起碼,你應該包括的「解釋」的輸出您的查詢。 – 2011-12-27 18:22:29

+0

當您明確指出要查詢的列時,是否有任何更改? – Origin 2011-12-27 18:23:22

+0

你有一個巨大的結果集,是你的'id'索引? – 2011-12-27 18:23:34

回答

0

沒有解釋它很難說,但最有可能你也需要在「狀態」列 索引。單個表查詢的慢度幾乎總是歸結爲執行全表掃描的查詢,而不是使用索引。

嘗試做:

explain SELECT * 
FROM users 
WHERE name IS NOT NULL 
AND name != '' 
AND (status IS NULL OR status = '0') 
order by id desc 
limit 50 

和後期的輸出。您可能會看到它正在執行全表掃描,因爲它沒有狀態索引。 here's some documentation on using "explain"。如果你想要更多的背景,this is a nice article你遇到的問題。

+0

嗨,下面是解釋的輸出。以下是解釋的輸出。 ID \t \t SELECT_TYPE表\t \t類型possible_keys \t \t鍵key_len \t \t參考行\t額外 1個\t \t SIMPLE用戶\t \t範圍名\t \t名258 \t \t NULL 226009 \t使用其中;使用filesort – 3iguru 2011-12-27 18:50:38

5

您應該一定有複合指數。包含您需要的所有字段作爲DBMS的單個查詢不能真正在單個查詢中使用多個索引。

一個OR子句並不真正適合索引,所以如果可以的話,我推薦將status設置爲NOT NULL。我假設NULL與零號碼沒有任何不同的含義。這將有助於實際使用索引。

我不知道多少name != ''已優化。語義上相同的將是name > ''(意思是後面的字母表),可能會爲您節省一些CPU週期。

然後你必須決定你的列出現的順序。經驗法則可以是基數,字段可能具有的值。

通過這樣的:

ALTER TABLE users ADD INDEX order1 (status, name, id DESC); 

編輯

您不必刪除索引。 MySQL會很快選擇最好的,而忽略其餘的。它們僅在UPDATE s上花費磁盤空間和一些CPU週期。但是,如果你在任何情況下都不需要它們,你當然可以將它們刪除。

長時間是因爲對錶格的訪問速度很慢。這可能是由動態長度字段(如TEXT或BLOB)引起的。如果你並不總是需要這些,你可以將它們移到一個雙輔助表所示:

users (id, name, status, group_id) 
profile (user_id, birthdate, gender, motto, cv) 

這樣的基本系統操作可以通過對用戶限制信息來完成,而所有其他的東西,其與用戶關聯的真正內容只有在真正需要時才需要使用。

EDIT2

您提示的MySQL將它指定(或更多的人)喜歡使用哪個索引:

SELECT id, name FROM users USE INDEX (order1) WHERE name != '' and status = '0' ORDER BY id DESC 
+0

正如你所說,我創建了一個索引「ALTER TABLE users ADD INDEX namstatid(name,status,id DESC);」。現在,如果我只選擇該列中的字段(名稱,狀態,ID),則需要0.8秒。但如果我使用其他列,大約需要26秒。另外,我應該刪除其他索引(目前我有2個索引,一個在狀態和其他名稱)。 – 3iguru 2011-12-27 19:35:42

+0

@ 3iguru請參閱編輯。 – vbence 2011-12-27 19:53:42

+0

當我使用「解釋選擇ID,來自用戶的其他字段,其中WHERE名稱不是NULL和名稱!=''AND(狀態IS NULL OR狀態='0')按ID desc limit 50排序」似乎沒有使用索引。那麼,即使在我們移動數據後,顯然也不會使用索引?在這種情況下,問題將持續存在。作爲將數據移動到子表格;修改其他各種相關的事情涉及..我想確保這將工作。唯一一次使用索引的是,如果我只使用索引中的字段。請告訴我你的想法。非常感謝! – 3iguru 2011-12-27 20:40:15