2016-09-08 80 views
0

我目前在一個MySQL用戶表名和姓字段,以及一個搜索框,在這裏他們可以輸入兩個,所以我的查詢基本上是最快的方式MySQL的

SELECT name,surname FROM user 
WHERE CONCAT(name,' ',surname) LIKE '@search%' 

這工作得很好,但是在大型表格上變得非常慢,即使名稱和姓氏列都被編入索引,並且當搜索被分解時,它很快,是否有一種方法來爲連接字段建立索引或者當兩個字段都編入索引時它們已經被編入索引,切換到全文索引會更快嗎?

+1

使用concat將防止MySQL使用索引,因爲它是派生值。長時間使用或是你最好的選擇。 '姓名LIKE'@ search%'或姓氏LIKE'@ search%'''。 –

+0

如果您不介意以更多空間和維護後勤爲代價獲得速度,則可以添加連接列的索引列並搜索該列。 – Amnon

回答

0

我正確的是假設@search被替換的東西?

如果您正在搜索「文字」,那麼FULLTEXT工程顯着更快。但是,請注意它的侷限性(停用詞,最小詞長度等)。

該特定嘗試CONCAT(name,' ',surname) LIKE '@search%'只會檢查'@search'的name的開頭;我懷疑這是不是你想要的。你想要什麼?

請記住name LIKE '@search%'name LIKE '%search%'要快很多,因爲它可以使用INDEX(name),我認爲你有嗎?

如果你有兩個INDEX(name)INDEX(surname),然後將是相當快的:

SELECT ... 
    WHERE name LIKE '@search%' 
UNION DISTINCT 
SELECT ... 
    WHERE surname LIKE '@search%'; 

這是因爲這兩個指標都可以使用。否則,他們不太可能都可以使用;相反,會有一個「表掃描」。 (使用OR如果你有一個老版本的MySQL,將不會如此。)

但是,如果用戶用'%'或'_'啓動@search,它將會很慢,因爲前導通配符會導致表掃描。

同時,如果你不檢查各種特殊字符,你是很受SQL注入

澄清

由於用戶後更容易分開輸入名稱,你可以測試:

WHERE name LIKE '@name%' 
    AND surname LIKE '@surname%' 

然後讓這兩個(萬一用戶縮短任一):

INDEX(name, surname) 
INDEX(surname, name) 

那些比你擁有什麼,更好。

由於數據輸入似乎是單個字段,因此請使用客戶端編程語言將其分爲@name和@surname。 (在SQL中可能但很雜亂;請參閱SUBSTRING_INDEX()。)

閱讀「組合索引」以瞭解爲什麼這些索引更好,以及爲什麼原始CONCAT特別低效。

+0

是@search被搜索所取代,我需要的是如果名字和姓氏是以空格作爲搜索文本(即'Rick James')分開輸入的,那麼名字Rick和姓氏James的用戶應該被返回。我可以做WHERE name LIKE'@ search%'和姓氏LIKE'%@ search%',但這會破壞姓氏上的索引並給我相同的問題,我可以使用全文作爲姓,但限制可能是如果只輸入姓氏的一個或兩個字符,即'Rick Ja' – JacoT

0

編輯:這假定您的搜索開始包括名字,直到完成繼續後面的名字。

只要你的搜索沒有一個通配符你可以隨時指數雙雙你的名字和姓字段作爲一個指數顯示爲多列索引MySQL手冊參考離開這裏:http://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html

那我們強制查詢使用多列索引。步驟如下:

1)創建索引

CREATE INDEX fullname ON table_name (name, surname) 

2)使用指數暗示告訴MySQL使用的多列索引查詢

SELECT name,surname FROM user USE INDEX (fullname) WHERE CONCAT(name,' ',surname) LIKE '@search%' 

當只要沒有通配符'%'在你的搜索開始,LIKE比較就會使用從左到右的索引。

最好的選擇的確是將您的字段更改爲FULLTEXT並利用MYSQL的新FULLTEXT搜索功能。下面是MySQL網站上的一個很好的例子,展示了這種搜索的實現方式:http://dev.mysql.com/doc/refman/5.7/en/fulltext-query-expansion.html