2011-05-20 159 views
14

我想用我的網絡全文進行搜索。我需要使用分頁進行搜索。我的數據庫有超過50,000行/每個表。我已經改變了我的表格,並使(title,content,date)成爲索引。表總是更新,仍然有一列id這是自動增加。而最新的date總是在表格的最後。優化mysql全文搜索

date varchar(10) 
title text 
content text 

但整個查詢時間將花費1.5+ seconds。我通過谷歌搜索了很多文章,有人寫道,只限制Index字段的字長可以幫助搜索更快。但作爲一個text類型,它can not改變一定長度一樣,(我試圖ALTER TABLE table_1 CHANGE標題標題TEXT(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,不工作)

date varchar(10) 
title text(500) 
content text(1000) 

所以,除了Sphinx和第三部分的腳本。如何優化全文搜索只有SQL?在此處查詢代碼:

(SELECT 
title,content,date 
FROM table_1 
WHERE MATCH (title,content,date) 
AGAINST ('+$Search' IN BOOLEAN MODE)) 
UNION 
(SELECT 
title,content,date 
FROM table_2 
WHERE MATCH (title,content,date) 
AGAINST ('+$Search' IN BOOLEAN MODE)) 
Order By date DESC 

謝謝。

+0

有沒有在表中的數據變化頻繁?或者這裏有所改變?倒置索引將始終加速全面測試 - 令人難以置信的搜索和靜態數據,這是非常容易實施/應用。如果有更新,這可能會變得更復雜 – 2011-05-21 00:04:04

+0

@ b.buchhold,是的,表中的數據是頻繁更新,更改。所以這很困難......至少我沒有任何好主意。所以要求幫助,如果有人有明智的方法。 – 2011-05-21 00:11:46

+0

它是(標題,內容,日期)或btree索引的全文索引嗎? – 2011-05-22 19:53:10

回答

9

根據問題的後續評論,您的列有一個btree索引,而不是全文索引。

對於MATCH(標題,內容)對搜索,你將需要:

CREATE FULLTEXT INDEX index_name ON tbl_name (title,content); 

我不知道它會接受有日期字段(後者可能是不相關的反正)。

+0

我認爲在這個實例中向FULLTEXT索引添加日期是確定的,因爲日期是varchar(10)而不是日期時間字段。另外,從一開始就沒有FULLTEXT就是一個死衚衕。爲你+1! – RolandoMySQLDBA 2011-05-23 02:22:32

+0

對不起,以後回覆。這將比'alter table table_1 ADD INDEX title(title)'更快'我仍然有一些問題。 1.是否將查詢切換爲'SELECT title,content,date FROM table_1 WHERE MATCH(index_name)AGAINST('+ $ Search'IN BOOLEAN MODE)'還是'MATCH(title,content,date)'?什麼是'index_name'用法?如果我創建了一個新表,像這樣?再次感謝';'CREATE TABLE TABLE_1( ID INT AUTO_INCREMENT NOT NULL PRIMARY KEY, 標題文本, 內容的文字, 日期VARCHAR(10), FULLTEXT(標題,內容,日期) )。 – 2011-05-26 08:17:17

+0

@Yuli:只需在當前表上創建索引:'在yourtable(title,content,date)上創建全文索引yourtable_fulltext_idx;'然後運行當前查詢。 – 2011-05-26 11:09:42

6

我有一個全面的計劃,爲您儘可能徹底優化MySQL的全文索引可能

你應該做的第一件事是:擺脫停止字

這惹惱了一些人的多年來因爲不知道over 600 words are excluded from a FULLTEXT index

Here is tabular view of those stopwords

有繞過這個

旁路選1)創建一個自定義的停止字兩種方式。

您實際上可以向MySQL提交您的首選停用詞表。這裏是默認值:

mysql> show variables like 'ft%'; 
+--------------------------+----------------+ 
| Variable_name   | Value   | 
+--------------------------+----------------+ 
| ft_boolean_syntax  | + -><()~*:""&| | 
| ft_max_word_len   | 84    | 
| ft_min_word_len   | 4    | 
| ft_query_expansion_limit | 20    | 
| ft_stopword_file   | (built-in)  | 
+--------------------------+----------------+ 
5 rows in set (0.00 sec) 

好吧,不要讓我們創建我們的停用詞列表。我通常將英文文章設置爲唯一的停用詞。

echo "a" > /var/lib/mysql/stopwords.txt 
echo "an" >> /var/lib/mysql/stopwords.txt 
echo "the" >> /var/lib/mysql/stopwords.txt 

接下來,將選項添加到/ etc/my。CNF加上允許1個字母,2個字母和3個字母的單詞

[mysqld] 
ft_min_word_len=1 
ft_stopword_file=/var/lib/mysql/stopwords.txt 

最後,重啓MySQL

service mysql restart 

如果您已經到位有FULLTEXT索引的任何表,必須刪除這些FULLTEXT索引並重新創建它們。

旁路選項2)重新編譯源代碼

的文件名是存儲/的myisam/ft_static.c。只要改變容納600多個單詞的C結構,以便它是空的。開心重新編譯!!!

既然FULLTEXT配置凝固,這裏是另一個主要方面來考慮:

寫正確的重構查詢,以使MySQL查詢優化器的工作原理正確的!

我現在提到的實際上沒有記錄:當您執行JOIN查詢並且WHERE子句包含用於FULLTEXT搜索的MATCH函數時,它往往會導致MySQL查詢優化器將查詢視爲全表掃描當涉及到在FULLTEXT索引中搜索invoved的列時。如果您計劃使用FULLTEXT索引來查詢表格,ALWAYS refactor your query to have the FULLTEXT search return only keys in a subquery and connect those keys to your main table。否則,FULLTEXT索引會讓MySQL查詢優化器陷入困境。

+1

選項一總是一個好主意,因爲每個語料庫(要查詢的文本元素的集合)都有自己的停用詞要求以及查詢目標。 – 2011-05-26 21:42:31

+2

由於許多原因,選項二不是一個好主意,其中最重要的是在推薦的過程之後,您將運行一個定製的,不可升級的Mysql版本。 – 2011-05-26 21:44:05