sql - LIKE 和正则表达式之间的 PostgreSQL 性能差异

标签 sql regex postgresql performance sql-like

有人能解释一下这些 SQL 之间如此大的性能差异吗?

SELECT count(*) as cnt FROM table WHERE name ~ '\*{3}'; -- Total runtime 12.000 - 18.000 ms
SELECT count(*) as cnt FROM table WHERE name ~ '\*\*\*'; -- Total runtime 12.000 - 18.000 ms
SELECT count(*) as cnt FROM table WHERE name LIKE '%***%'; -- Total runtime 5.000 - 7.000 ms

如您所见,LIKE 运算符和简单正则表达式之间的差异不止一倍(我认为 LIKE 运算符在内部会被转换为正则表达式,应该没有任何区别)

那里有将近 13000 行,“名称”列是“文本”类型。没有与表中定义的“名称”列相关的索引。

编辑:

对它们中的每一个进行解释分析:

EXPLAIN ANALYZE SELECT count(*) as cnt FROM datos WHERE nombre ~ '\*{3}';

Aggregate  (cost=894.32..894.33 rows=1 width=0) (actual time=18.279..18.280 rows=1 loops=1)
  ->  Seq Scan on datos (cost=0.00..894.31 rows=1 width=0) (actual time=0.620..18.266 rows=25 loops=1)
        Filter: (nombre ~ '\*{3}'::text)
Total runtime: 18.327 ms

EXPLAIN ANALYZE SELECT count(*) as cnt FROM datos WHERE nombre ~ '\*\*\*';
Aggregate  (cost=894.32..894.33 rows=1 width=0) (actual time=17.404..17.405 rows=1 loops=1)
  ->  Seq Scan on datos  (cost=0.00..894.31 rows=1 width=0) (actual time=0.608..17.396 rows=25 loops=1)
        Filter: (nombre ~ '\*\*\*'::text)
Total runtime: 17.451 ms

EXPLAIN ANALYZE SELECT count(*) as cnt  FROM datos WHERE nombre LIKE '%***%';
Aggregate  (cost=894.32..894.33 rows=1 width=0) (actual time=4.258..4.258 rows=1 loops=1)
  ->  Seq Scan on datos  (cost=0.00..894.31 rows=1 width=0) (actual time=0.138..4.249 rows=25 loops=1)
        Filter: (nombre ~~ '%***%'::text)
Total runtime: 4.295 ms

最佳答案

text LIKE text 运算符(~~)由like_match.c中的特定C代码实现。 .它是完全独立于正则表达式的临时代码。看评论,明显是专门优化的,只实现%_作为通配符,尽可能短路到导出,而正则表达式引擎更复杂几个数量级。

请注意,在您的测试用例中,就像正则表达式与 LIKE 相比不是最优的一样,LIKEstrpos(name, '** *') > 0

strpos 是用 Boyer–Moore–Horspool algorithm 实现的它针对搜索文本中几乎没有部分匹配的大型子字符串进行了优化。

这些函数在内部进行了合理优化,但是当有多种方法实现同一目标时,选择可能最好的方法仍然是调用者的工作。 PostgreSQL 不会为我们分析要匹配的模式并将 regexp 转换为 LIKE 或将 LIKE 转换为 strpos 基于该分析。

关于sql - LIKE 和正则表达式之间的 PostgreSQL 性能差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29467654/

相关文章:

php - 处理 CSV 中的逗号

ruby-on-rails - rails has_one 通过关系不存在

mysql - 忽略子字符串匹配的最高值的列

php - JS OnClick 事件将执行 php 代码块

RegEx PowerShell 匹配

postgresql - 有没有办法在 Postgres 中禁用函数重载

Postgresql 使用函数创建用户

sql - 合并两个备份文件中的表 - SQL Server

sql - 如何根据不同的条件从同一个表的不同行中检索数据

python - 如何在python中分隔符的第一个实例上拆分字符串