我们这里有一个简单的sql问题.在varchar列中,我们希望在字段中的任何位置搜索字符串.实现此性能的最佳方法是什么?显然一个指数在这里没有任何帮助,还有其他任何技巧吗?
我们正在使用MySQL并拥有大约300万条记录.我们需要每秒执行许多这些查询,因此我们真正尝试以最佳性能实现这些查询.
到目前为止,最简单的方法是:
Select * from table where column like '%search%'
我应该进一步指定该列实际上是一个长字符串,如“sadfasdfwerwe”,我必须在此列中搜索“asdf”.所以他们不是句子,而是试图匹配其中的一个词.全文搜索仍然有用吗?
解决方法
看看我的演讲
Practical Fulltext Search in MySQL.
我比较了:
> LIKE谓词
> Regular expression谓词(不比LIKE好)
> MyISAM FULLTEXT索引
> Sphinx Search
> Apache Lucene
>反向索引
>谷歌Custom Search Engine
今天我将使用的是Apache Solr,它将Lucene置于具有一系列额外功能和工具的服务中.
你的评论:啊哈,好吧,不.我提到的全文搜索功能都没有帮助,因为它们都假设某种词边界
有效地找到任意子串的另一种方法是N-gram方法.基本上,创建N个字母的所有可能序列的索引,并指向每个相应序列出现的字符串.通常,这是通过N = 3或trigram完成的,因为它是匹配较长子串并将索引保持在可管理大小之间的折衷点.
我不知道任何透明地支持N-gram索引的sql数据库,但您可以使用倒排索引自己设置它:
create table trigrams ( trigram char(3) primary key ); create table trigram_matches ( trigram char(3),document_id int,primary key (trigram,document_id),foreign key (trigram) references trigrams(trigram),foreign key (document_id) references mytable(document_id) );
现在用艰难的方式填充它:
insert into trigram_matches select t.trigram,d.document_id from trigrams t join mytable d on d.textcolumn like concat('%',t.trigram,'%');
当然这需要一段时间!但是一旦完成,你可以更快地搜索:
select d.* from mytable d join trigram_matches t on t.document_id = d.document_id where t.trigram = 'abc'
当然你可以搜索超过三个字符的模式,但倒排索引仍然有助于缩小你的搜索范围:
select d.* from mytable d join trigram_matches t on t.document_id = d.document_id where t.trigram = 'abc' and d.textcolumn like '%abcdef%';