LIKE 是如何实现的?

Nic*_*ick 24 mysql postgresql performance full-text-search pattern-matching

谁能解释一下 LIKE 运算符是如何在当前数据库系统(例如 MySQL 或 Postgres)中实现的?或者指出一些解释它的参考资料?

天真的方法是检查每条记录,在感兴趣的字段上执行正则表达式或部分字符串匹配,但我有一种感觉(希望)这些系统做一些更聪明的事情。

Erw*_*ter 29

除了 Justin Cave 所写的内容之外,从PostgreSQL 9.1 开始,您可以使用( ) 或( )加快任何搜索速度,也可以LIKE( ~~)加快基本的正则表达式匹配。使用带有 GIN 或 GiST 索引的模块pg_trgm提供的运算符类来加速非左锚定的表达式。要安装扩展,请为每个数据库运行一次:ILIKE~~*~LIKE

CREATE EXTENSION pg_trgm;
Run Code Online (Sandbox Code Playgroud)

创建表单的索引

CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);
Run Code Online (Sandbox Code Playgroud)

或者:

CREATE INDEX tbl_col_gist_trgm_idx ON tbl USING gist (col gist_trgm_ops);
Run Code Online (Sandbox Code Playgroud)

创建和维护GIN 或 GiST 索引会带来成本,但如果您的表没有大量写入,这对您来说是一个很棒的功能。

Depesz在他的博客中写了一篇关于新功能的优秀文章

GIN 还是 GiST?

手册中的这两句话应该提供一些指导

GiST 和 GIN 索引之间的选择取决于 GiST 和 GIN 的相对性能特征,这在别处讨论。根据经验,GIN 索引的搜索速度比 GiST 索引快,但构建或更新速度较慢;所以 GIN 更适合静态数据,而 GiST 更适合经常更新的数据。

但是对于使用距离运算符的“最近邻居”类型的查询<->

这可以通过 GiST 索引非常有效地实现,但不能通过 GIN 索引实现。

  • 读到这里我想知道是使用 GIN 还是 GiST。根据我读到的内容,GIN 索引维护成本更高但搜索速度更快,而 GiST 索引维护成本更低但搜索速度更慢。这意味着 GIN 索引通常应该用于相对静态的数据,而 GiST 索引更适合用于更严重的变异表。 (3认同)

Jus*_*ave 20

不,这几乎就是他们正在做的事情。现在,如果没有前导通配符并且该字段被索引,这是通常的情况,数据库引擎可以将正则表达式应用于索引。所以,例如,如果你写

SELECT *
  FROM employees
 WHERE last_name LIKE 'Cav%'
Run Code Online (Sandbox Code Playgroud)

数据库可以使用索引LAST_NAME来查找姓氏以“Cav”开头的所有行。另一方面,如果你有类似的东西

SELECT *
  FROM employees
 WHERE last_name LIKE '%av%'
Run Code Online (Sandbox Code Playgroud)

数据库必须扫描整个表(或整个索引)并根据完整LAST_NAME值评估表达式。显然,这是非常昂贵的。

大多数更好的关系数据库都可以通过构建不同种类的索引和文本目录以更有效的方式进行全文搜索,但这些不使用 LIKE 关键字。例如,这里有一篇很好的文章,讨论了 PostgreSQL 中的全文搜索

  • Oracle 可以使用带有前导百分比的索引。如果正在搜索的数据代表行的一小部分,那么提示可以强制它使用索引并加快执行速度。请参阅 http://laurentschneider.com/wordpress/2009/07/how-to-tune-where-name-likebc.html。 (4认同)

Sta*_*hns 6

说到 MySQL,通配符 (%) 的位置有所不同。如果文本的第一部分指定为where first_name like 'Sta%',那么数据库引擎将只搜索以 S 开头的单词的较小子集,然后转到 St,然后是 Sta 等。如果您执行类似的操作where first_name like '%stan%',则和整个扫描列将是必需的。您还可以查看也进行自然语言搜索的全文索引。在此处查看 MySQL 文档。