2011-05-20 96 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