2012-03-29 97 views
0

SQL:對用戶MySQL的LIKE查詢時間太長

 SELECT 
      COUNT(usr.id) as `total_results` 
     FROM 
      users as usr 
      LEFT JOIN profile as prof 
       ON prof.uid = usr.uid 
     WHERE 
      usr.username LIKE '%a%' 
      OR 
      prof.name LIKE '%a%' 

指標:在個人

index1 - uid 
index2 - uid,name 
index3 - name 

uid - uid 
username - username 

指標說明:

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 PRIMARY  usr  ALL  NULL NULL NULL NULL 18387 
1 PRIMARY  prof ref  index2,index1 index2 8 site.usr.uid 1 Using where 
2 DEPENDENT SUBQUERY sub  ref  i3,index1,index2 i3 16 site.usr.uid,const 1 Using index 

以上查詢大約需要0.1221

我該如何讓它運行得更快?

+1

刪除你的'LIKE'上的開始'%' – Lamak 2012-03-29 15:54:00

+1

你想達到什麼目的?您是否真的想要統計所有名稱或用戶名中帶有字母「a」的條目? – liquorvicar 2012-03-29 15:58:24

+0

@liquorvicar是的,我正在嘗試獲取搜索記錄的數量 – fxuser 2012-03-29 16:00:23

回答

0

我刪除了這個查詢,以便它不會顯示總結果計數當一個搜索完成。

似乎是一個臨時解決方案,甚至是永久性的。

3

LIKE子句中的初始%意味着這些列的索引不能使用。我相信MySQL full text index可能會做你想做的。

0

它儘可能多地使用索引(兩個主鍵都用於左連接)。主要的問題是LIKE'%a%',因爲在這種情況下它不能使用索引(如果它是'%',它將能夠在用戶名和名稱上使用索引)。你可以嘗試什麼(不知道這是否會加快速度)是使用concat(usr.username,prof.name),如'%a%',但你可能不會注意到任何區別。

全文索引不起作用,因爲全文索引在搜索整個單詞時非常有用。

無論如何,對於查詢你有你的名字和用戶名索引是無用的,只是佔用空間,所以我會刪除它們。如果LIKE'a%'滿足您的需求,那麼這些索引就有意義。

如果'a%'不能滿足您的需求,您可以查看其他選項,例如mysql查詢緩存(如果您希望頻繁重複查詢)。

+0

所以我做這個方法,我用來搜索或沒有什麼可以加速的東西?不能相信沒有任何方法... – fxuser 2012-03-29 16:01:28

+0

據我所知,沒有辦法寫它工作得更快,並保持相同的語義。 – 2012-03-29 16:07:57

6

要匹配的字符串的開始處的%使得索引無法使用。開頭的通配符使索引無效,並且MySQL必須在每個行的該列內進行搜索。它不能跳下去。如果您知道您正在搜索的項目將位於字段開頭的開頭,則可以刪除開始的'%'。但是,如果您正在尋找'steve',我的回答將會返回'steve','steven','steve-boss',而不是'boss-steve'或'realsteve'。

+0

所以其他網站如何使用搜索?有沒有更好的方法可以使用? – fxuser 2012-03-29 16:02:26

+0

@fxuser - 其他網站不只是搜索單個字符。像谷歌這樣的大型網站不會使用任何特定於這種搜索的關係數據庫。爲此,最好使用全文索引,但如果您希望搜索包含字符'a'的所有用戶,那麼它的作用不同於僅搜索單個字符 – Lamak 2012-03-29 16:06:47

+0

@fxuser,然後在MySQL中沒有更快的方式。你將不得不升級你的硬件或重新設計你的數據庫。老實說,18k的記錄似乎並不像查詢那麼慢。 – 2012-03-29 18:20:19

0

1)購買更快的數據庫服務器。

2)重新設計你的數據庫,這樣你就不必在兩個地方的用戶名看或只允許用戶搜索的一個或另一個