对于任何有实际经验的人来说,LIKE查询在
不太好(我想我有过900k的搜索量,不能说我有数百万行点赞的经验).
通常,您应该尽可能地限制搜索,但这取决于表 struct 和应用程序用例.
此外,在大约Web个用例中,可以使用一些技巧来实际提高性能和用户体验,比如为单独的关键字编制索引,并创建关键字表和rowcontainskeyword(id_keyword,id_row)表.关键字表与Ajax一起使用来建议搜索项(简单的单词),并将它们编译成整数--id_关键字.在这一点上,查找包含这些关键字的行变得更快了.一次更新表中的一行也相当有效;当然,批量更新会变成明确的"不要".
如果只使用+运算符,这与full text MATCH..IN BOOLEAN MODE已经执行的操作没有太大不同:
SELECT * FROM arts WHERE MATCH (title) AGAINST ('+MySQL +RDBMS' IN BOOLEAN MODE);
您可能需要一个InnoDB表来实现这一点:
布尔全文搜索具有以下特点:
- 它们不会自动按相关性递减的顺序对行进行排序.
...
- InnoDB表需要Match()表达式的所有列上的全文索引才能执行布尔查询.即使没有全文索引,针对MyISAM搜索索引的布尔查询也可以工作,尽管以这种方式执行的搜索会相当慢.
...
- 它们不使用适用于MyISAM搜索索引的50%阈值.
你能提供更多关于具体案件的信息吗?
update: the AJAX way
设置:您将所有的title
分成单词.这将很快为您提供title_words
张桌子( id integer not null autoincrement, word varchar(50) )
和一张很大的title_contains_word ( word_id integer, title_id integer )
张桌子.
如果您有title_words
0万个标题,平均4个单词(对于书籍来说似乎是合理的,而对于论文来说就不是这样了),那么您可以预期有一个5000行title_words
行的表和一个包含两个整数列的4000万个表;这大约是400MB的额外数据.
对于搜索,用户开始输入一个单词,您可以从标题单词中 Select autocomplete个单词.一旦这样做了,查询就变成了一个单词ID列表;当然,不在任何标题中的单词都不能输入,所以立即免费地给出否定结果.
现在实际的搜索可以通过几种方式进行,但是我喜欢的一种方式是在每个用户 Select 之后运行SELECT COUNT(*) FROM title_contains_word WHERE word_id={id}
,before真正的搜索就开始了.
这允许构建从rarest个单词开始的复合查询或公用表表达式.实际上,如果任何单词的计数低于(比方说)20,您可以 Select 所有(平均)8个TCW行并获得它们所有相关单词的ID,然后只需(在MySQL之外)验证是否存在一个标题ID,以便查询的所有单词ID都存在一对(title ID,wordID).
即使你不得不诉诸最粗暴的形式,
SELECT a.title_id
FROM title_contains_word AS tcw1
JOIN title_contains_word AS tcw2 USING (title_id)
JOIN title_contains_word AS tcw3 USING (title_id)
JOIN title_contains_word AS tcw4 USING (title_id)
...
WHERE (tcw1.word_id = {id1})
AND (tcw2.word_id = {id2})
...
连接将由非常小的虚拟缓冲表组成,扫描所需的时间非常短.
一旦有了所有相关的标题ID,您就可以直接从多行大型DBusing the primary key title_id中运行SELECT.这最后一次搜索也应该是火速进行的.