2011-03-09 73 views
2

由於使用ORDER BY,所以查詢速度很慢。現在我明白爲什麼它很慢,但我不知道如何讓它更快。使用ORDER BY和LIMIT的查詢非常緩慢

該表有900.000條記錄。 (之所以慢)

SELECT SQL_NO_CACHE id, name 
FROM users where is_provider = 0 
AND activated_at IS NOT NULL 
AND is_ngo = 0 
AND deleted_at is NULL 
AND is_cancelled = 0 
ORDER BY name 
LIMIT 60000, 90; 

我使用限制,因爲我使用分頁。 SQL_NO_CACHE,因爲我不想使用緩存進行測試。

這個查詢需要60秒,這太長了。這是一個後臺任務,所以如果我可以在5秒內減少它將是好的

我有索引在activated_at列和deleted_at這是時間字段。其他的是布爾值,所以不需要索引。

謝謝

回答

3

我認爲索引是答案,但你必須找出正確的索引查詢,所以你應該試試這個:

EXPLAIN SELECT SQL_NO_CACHE id, name 
FROM users where is_provider = 0 
AND activated_at IS NOT NULL 
AND is_ngo = 0 
AND deleted_at is NULL 
AND is_cancelled = 0 
ORDER BY name 
LIMIT 60000, 90; 

在本很老了徹底詳細的,但有用的文章:
http://www.databasejournal.com/features/mysql/article.php/1382791/Optimizing-MySQL-Queries-and-Indexes.htm

+0

對於閱讀此答案的其他人:我沒有找到有用的文章。總之,除非你對MySQL非常陌生,並且還沒有添加索引,否則我會一直在尋找答案。 – nostromo 2013-02-28 06:21:48

1

我想這是按名稱排序使它變慢。

要測試,刪除ORDER子句並檢查需要多長時間。

名稱字段可能應該編入索引時,您要按它的順序。

+0

感謝您的快速回復。是的,我有一個名字索引。問題是,我需要按名稱排序... – 2011-03-09 17:11:19

1

我建議在最有選擇性的布爾字段上添加一個索引,也就是說,如果數據庫中只有5%的行有is_provider = 0,那麼您可以顯着減少需要掃描其他行的行數屬性。如果分佈是50/50,那麼沒有多大意義,但我會看看分佈,並讓它指導您確定哪些索引可能會有所幫助。當然,您應該以實際表現(包括您可能有其他查詢的表現)爲指導。

+0

感謝您的回答。我玩過指標,但把它或刪除它沒有任何區別 – 2011-03-09 17:41:23

+1

@邁克爾 - 你有沒有嘗試過一個複合索引,包括名稱?應該減少分類所需的時間。你也可以嘗試重構你的查詢來幫助它選擇正確的索引,也許使用嵌套。 – tvanfosson 2011-03-09 18:07:31

0

或者,刪除Order By子句並在讀取記錄後執行您的訂購。它將工作放在客戶端,但如果數據庫很慢(如此處所示),那可能會更可靠和更快。

乾杯,

丹尼爾

0

您可以嘗試

SELECT * FROM (SELECT SQL_NO_CACHE id, name 
FROM users where is_provider = 0 
AND activated_at IS NOT NULL 
AND is_ngo = 0 
AND deleted_at is NULL 
AND is_cancelled = 0 
ORDER BY name) t 
LIMIT 60000, 90; 

避免ORDER BY和LIMIT在一起。