在SQL中实现子字符串搜索的最佳方法是什么?

ero*_*ppa 8 mysql sql full-text-search query-optimization

我们这里有一个简单的SQL问题.在varchar列中,我们希望在字段中的任何位置搜索字符串.实现此性能的最佳方法是什么?显然,一个指数在这里没有任何帮助,其他任何技巧?

我们使用MySQL并拥有大约300万条记录.我们需要每秒执行许多这些查询,因此我们真正尝试以最佳性能实现这些查询.

到目前为止,最简单的方法是:

Select * from table where column like '%search%'
Run Code Online (Sandbox Code Playgroud)

我应该进一步指定该列实际上是一个长字符串,如"sadfasdfwerwe",我必须在此列中搜索"asdf".所以他们不是句子而是试图匹配他们中的一个词.全文搜索仍然有用吗?

Bil*_*win 15

查看我的演示文稿MySQL中的实用全文搜索.

我比较了:

今天我将使用的是Apache Solr,它将Lucene置于一项带有一系列额外功能和工具的服务中.


你的评论:啊哈,好吧,不.我提到的全文搜索功能都没有帮助,因为它们都假设某种词边界

有效地找到任意子串的另一种方法是N-gram方法.基本上,创建N个字母的所有可能序列的索引,并指向每个相应序列出现的字符串.通常,这是通过N = 3或三元组来完成的,因为它是匹配较长子串并将索引保​​持在可管理大小之间的折衷点.

我不知道任何透明地支持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)
);
Run Code Online (Sandbox Code Playgroud)

现在用艰难的方式填充它:

insert into trigram_matches
  select t.trigram, d.document_id
  from trigrams t join mytable d
    on d.textcolumn like concat('%', t.trigram, '%');
Run Code Online (Sandbox Code Playgroud)

当然这需要一段时间!但是一旦完成,你可以更快地搜索:

select d.*
from mytable d join trigram_matches t
  on t.document_id = d.document_id
where t.trigram = 'abc'
Run Code Online (Sandbox Code Playgroud)

当然你可以搜索超过三个字符的模式,但倒排索引仍然有助于缩小你的搜索范围:

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%';
Run Code Online (Sandbox Code Playgroud)

  • PostgreSQL有一个pg_trgm contrib包,它引入了一种索引三元组的方法.http://www.postgresql.org/docs/current/static/pgtrgm.html (7认同)

Wri*_*ken 0

如果你想匹配整个单词,请查看FULLTEXT索引 & MATCH() AGAINST()。当然,请承受数据库服务器的负载:根据您的特定需求将结果缓存适当的时间。