2014-01-16 72 views
0

注:優化MySQL查詢與LIKE操作符10K記錄

所以,我算了一下,真正的問題是,因爲我使用tagids IN子句的。更改文本搜索的部分查詢並沒有多大幫助。任何想法如何改善查詢?

查詢在服務器上運行時間過長。這裏Partha S是用戶輸入的搜索項目。表聯繫人包含個人信息,標籤包含類別名稱和ID; contacts2tags表中包含contactid和tagid,其值分別與聯繫人和標籤中的id類似。

SELECT * 
    FROM 
    (
    SELECT *, 
    IF 
    (
    first_name LIKE 'Partha S' 
    OR last_name LIKE 'Partha S' 
    OR phone_number LIKE 'Partha S' 
    OR mobile_number LIKE 'Partha S' 
    OR email_address LIKE 'Partha S' 
    OR address LIKE 'Partha S' 
    OR organization LIKE 'Partha S' 
    OR other LIKE 'Partha S' 
    OR sector LIKE 'Partha S' 
    OR designation LIKE 'Partha S' 
    OR concat (first_name, ' ', last_name) LIKE 'Partha S' 
    OR concat (last_name, ' ', first_name) LIKE 'Partha S', 
    1, 
    0) 
    as exact, 
    IF 
    (
    (
    first_name LIKE '%Partha%' 
    OR last_name LIKE '%Partha%' 
    OR phone_number LIKE '%Partha%' 
    OR mobile_number LIKE '%Partha%' 
    OR email_address LIKE '%Partha%' 
    OR address LIKE '%Partha%' 
    OR organization LIKE '%Partha%' 
    OR other LIKE '%Partha%' 
    OR sector LIKE '%Partha%' 
    OR designation LIKE '%Partha%') 
    AND 
    (
    first_name LIKE '%S%' 
    OR last_name LIKE '%S%' 
    OR phone_number LIKE '%S%' 
    OR mobile_number LIKE '%S%' 
    OR email_address LIKE '%S%' 
    OR address LIKE '%S%' 
    OR organization LIKE '%S%' 
    OR other LIKE '%S%' 
    OR sector LIKE '%S%' 
    OR designation LIKE '%S%') 
    , 
    1, 
    0) 
    as normal 
    FROM contacts 
    WHERE id in 
    (
    SELECT DISTINCT contacts.id 
    from contacts INNER 
    JOIN contacts2tags ON contacts.id = contacts2tags.contactid 
    WHERE (tagid in (178))) 
    ) 
    d 
    WHERE exact = 1 
    OR normal = 1 
    ORDER BY exact desc, 
    last_name asc LIMIT 0, 
    20 

UPDATE: 具體根據建議,我除去精確搜索AGAINST LIKE運算符,以及用於MATCH(..)(..)代替LIKE在後者的情況下。儘管第一次更改確實提高了性能,但使用MATCH()AGAINST()並沒有令人驚訝地改變執行時間。這是更新後的查詢。 PS我嘗試使用匹配(所有列)反對(搜索項目)和匹配(單列)反對(搜索項目)結合OR。請建議。感謝

 SELECT * 
    FROM 
    (
    SELECT *, 
    IF 
    (
     first_name ='Partha S' 
     OR last_name ='Partha S' 
     OR phone_number ='Partha S' 
     OR mobile_number ='Partha S' 
     OR email_address = 'Partha S' 
     OR address ='Partha S' 
     OR organization ='Partha S' 
     OR other ='Partha S' 
     OR sector ='Partha S' 
     OR designation ='Partha S' 
     OR concat (first_name, ' ', last_name) ='Partha S' 
     OR concat (last_name, ' ', first_name) ='Partha S', 
     1, 
     0) 
     as exact, 
     IF 
     (match(first_name,last_name,phone_number,mobile_number,email_address, address,organization,other,sector,designation) against('Partha')     
    OR match(first_name,last_name,phone_number,mobile_number,email_address,address,organization,other,sector,designation) against('S') 


    , 
    1, 
    0) 
    as normal 
    FROM contacts 
    WHERE id in 
    (
    SELECT DISTINCT contacts.id 
    from contacts INNER 
    JOIN contacts2tags ON contacts.id = contacts2tags.contactid 
    WHERE (tagid in (178))) 
    ) 
    d 
    WHERE exact = 1 
    OR normal = 1 
    ORDER BY exact desc, 
    last_name asc LIMIT 0, 
     20 

回答

1

一種優化是,在exact情況下,你不需要使用像(你只能用通配符 - %)。

另一件事,你可以做,使事情更快地被添加索引到你會在被搜索的Fileds。

而且,只有當你使用MyISSAM作爲存儲引擎(用於該表),您可以使用全文搜索這樣

SELECT * FROM normal WHERE MATCH(標題,正文)AGAINST( 'Queried_string')

first_name LIKE '%S%' 
OR last_name LIKE '%S%' 
OR phone_number LIKE '%S%' 
OR mobile_number LIKE '%S%' 
OR email_address LIKE '%S%' 
OR address LIKE '%S%' 
OR organization LIKE '%S%' 
OR other LIKE '%S%' 
OR sector LIKE '%S%' 
OR designation LIKE '%S%') 

似乎帶來很少的VA從整個過程來看。

希望這會有所幫助。

+1

謝謝..我刪除LIKE建議。它有幫助 – user415

0

這不只是所有的LIKE S,也是OR秒。 即使對於使用LIKE的條件,索引也會被使用。因此,爲了加快查詢速度,您可以爲每個表格創建一個非常大的索引,並將所有搜索字段組合在一起。

但是,如果您確實想構建搜索引擎,則可能需要考慮使用Sphinx或ElasticSearch而不是像這樣的MySQL怪物查詢。

+0

我已經添加了索引,它提高了性能,但不是很好。以某種方式索引在單獨的列而不是索引爲每個表更好地工作。但它仍然不令人滿意..感謝 – user415

+0

我應該指出,當您在末尾使用帶有通配符的'LIKE'時,會使用索引,但在搜索字符串開頭處有通配符時不會使用索引。這也適用於單列索引。但是我認爲對於這樣的事情,你應該使用FULLTEXT索引或者搜索引擎,儘管他們在搜索詞的中間部分時也會遇到困難(當搜索'oba'時通常不會起作用'查找'foobar')。除了這些限制,像這樣的搜索將比使用LIKE更快。 – GolezTrol

+0

所以我嘗試使用FULLTEXT索引並用MATCH()反對()替換LIKE,但是性能仍然相同..我不知道爲什麼?我嘗試了兩種方式爲具有多列的聯繫人表創建FULLINDEX,併爲每列創建一個。兩者工作差不多。我實際上使用jQuery的flexigrid這個查詢。你能否建議如何進一步改進,或者如何去推薦你所建議的工具?謝謝! PS我已經在我的本地服務器上運行這個修改後的查詢,並且運行時間爲0.0040s。將檢查實際服務器 – user415

0

您可能想看看match()against() MySQL的功能。

這裏是他們的文檔一些示例代碼

mysql> CREATE TABLE articles (
    -> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, 
    -> title VARCHAR(200), 
    -> body TEXT, 
    -> FULLTEXT (title,body) 
    ->) ENGINE=MyISAM; 
Query OK, 0 rows affected (0.00 sec) 

mysql> INSERT INTO articles (title,body) VALUES 
    -> ('MySQL Tutorial','DBMS stands for DataBase ...'), 
    -> ('How To Use MySQL Well','After you went through a ...'), 
    -> ('Optimizing MySQL','In this tutorial we will show ...'), 
    -> ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), 
    -> ('MySQL vs. YourSQL','In the following database comparison ...'), 
    -> ('MySQL Security','When configured properly, MySQL ...'); 
Query OK, 6 rows affected (0.00 sec) 
Records: 6 Duplicates: 0 Warnings: 0 

mysql> SELECT * FROM articles 
    -> WHERE MATCH (title,body) AGAINST ('database'); 
+----+-------------------+------------------------------------------+ 
| id | title    | body          | 
+----+-------------------+------------------------------------------+ 
| 5 | MySQL vs. YourSQL | In the following database comparison ... | 
| 1 | MySQL Tutorial | DBMS stands for DataBase ...    | 
+----+-------------------+------------------------------------------+ 
2 rows in set (0.00 sec) 

在這裏閱讀更多 - http://dev.mysql.com/doc/refman/4.1/en/fulltext-natural-language.html