2013-10-18 168 views
0

我有80,000個客戶,有4個組。現在我想查找2組用戶在mysql中查詢。我的查詢是象下面這樣:通過查詢進行排序花費的時間太長

select c.customers_firstname as recipient_firstname, 
     c.customers_lastname as recipient_lastname, 
     c.customers_id as recipient_id, 
     c.customers_email_address as recipient_email_address 
from customers c 
where customers_group_id = '1' OR customers_group_id = '3' 

當我運行在phpMyAdmin此查詢我得到的結果是:顯示行0 - 29(59815總計,查詢花費0.0034秒)

但是,當我加入順序在此查詢結果的時間ORDER BY recipient_firstname ASC顯示行0 - 29(59815總計,查詢花費0.2607秒)

順序通過查詢花費太多時間的結果。

我想通過查詢減少訂單的時間。

如果還有其他方法可以在較短時間內獲得相同結果,請幫助。

+3

在'recipient_firstname'字段創建一個索引。另外,試一下:'where customers_group_id IN(1,3)' – hjpotter92

+1

好吧,和往常一樣,在針對mysql執行特定查詢時遇到問題:嘗試使用mysql中的'explain'功能!它告訴你問題在哪裏! – arkascha

回答

3

您需要recipient_firstname字段的索引(真的是customers.customers_firstname)。索引允許對結果集進行有序的線性時間迭代。

如果您沒有索引,則結果集必須彙總並排序。這個排序將是n log n。對於大集合,這顯然很慢,如果它不適合內存(並且60k記錄可能不取決於配置),它將執行非常慢的基於文件的排序。

tl; dr您需要索引。 recipient_firstname上的索引將使查詢在性能上非常接近非ORDER BY版本。


順便說一句,如果customers_group_id是一個整數字段,使用整數字面值,而不是字符串。它可能不會有所作爲,但它是誤導性的,實際上有一些情況很重要。


根據具體情況,可能還需要在組ID上加上索引。對於小集合,結果可以在集合被構建時被過濾,但對於大的結果集,這將最終需要相當大的磁盤大量全表掃描。

+2

你不覺得索引也應該包含group_id嗎?因爲這是WHERE的一部分,並忽略這可能會使這個查詢慢以後更多的數據,即使不是現在 –

+0

@Hanky웃Panky儘快他的無序查詢正在運行,我假設他已經有一個group_id索引。 – Corbin

+0

我認爲這可能是因爲它的整數值和80k記錄對整數比較來說沒有任何意義。可能值得一提,以補充您的答案 –

0

您需要create index上應用了order by子句的列。

CREATE INDEX index_name ON customers (customers_firstname); 
1

嘗試創建索引(customers_group_id, customers_firstname) - 這應該工作。

+0

當我們知道這只是一個錯字而不會改變答案的設計時,爲什麼不去編輯它 –

3

你必須在customers_firstname場指數:這將加快ORDER BY也將放緩WHERE(這可能是現在索引)。

所以索引必須是customers_group_id, customers_firstname按此順序。

CREATE INDEX my_query_ndx 
    ON customers (customers_group_id, customers_firstname); 

從理論上講,你可以放大指數是一個覆蓋指數和包含兩個關鍵領域後,您在SELECT要求的所有其他領域。但是,保持這種指數是昂貴的。你將不得不平衡優點和缺點。如果表格非常「寬」,則可能有利於對組ID,名字,姓氏,ID和電子郵件進行索引。

小(或不那麼小)查詢改進

where customers_group_id = '1' OR customers_group_id = '3' 

這可以被改寫爲清楚(這改變不了什麼)作爲

WHERE customers_group_id IN ('1','3') 

但現在,無論是customer_group_id是一個整數字段,或它不是。如果是,那麼最好的治療是這樣的:

WHERE customers_group_id IN (1, 3) 

在某些情況下,你可以提前規劃你的ID,以便例如3組實際上是2組,即組你可能感興趣的是連續的。這樣,您可以將查詢重寫爲variable < valuevariable > valuevariable BETWEEN,這是OR的兩倍。隨着大OR集,你可以輕鬆獲得4倍加速。

如果它不是一個整數字段,那麼盡一切辦法努力使其成爲一體。整數性能(和索引大小)將大大受益(但請注意,對於字符串,'3'大於'12',就像'C'大於'AB'一樣;所以,類型轉換不一定沒有邊效果)。