Postgres中的LIKE和〜之间的区别

我已经被指示“不要打扰LIKE ”,而是使用~LIKE什么问题?和不同?

在这种情况下是否有一个名字,或者有人说“使用代字符运算符”?

~是正则expression式的运算符,并且具有这种隐含的能力。 您可以指定全部的正则expression式通配符和量词; 有关详细信息,请参阅文档的第9.7.3节 。 它肯定比LIKE更强大,应该在需要的时候使用,但是它们有不同的用途。

LIKE没有错,IMO也没有理由赞成。 恰恰相反。 LIKE是SQL标准。 所以是SIMILAR TO ,但没有得到广泛的支持。 PostgreSQL的~ operator (或posix正则expression式匹配运算符 )不是SQL标准。

出于这个原因,我更喜欢使用LIKE ,当我需要完整正则expression式的时候,我只使用~ 。 如果我需要移植数据库,那么这个问题就会受到影响。 当LIKEfunction不够强大时,我倾向于使用SIMILAR TO ,但在Erwin的评论之后,我想我会停止这样做,并在LIKE没有完成这个工作时使用~

另外,如果数据库位于C语言环境或索引具有text_pattern_ops ,则PostgreSQL可以使用LIKESIMILAR TO的b-tree索引来进行前缀search(例如LIKE 'TEST%' )。 与我之前写的相反,Pg也可以使用这样一个索引来作为左锚posix regex,它只是需要一个明确的'^ TEST。*',所以正则expression式只能从头开始匹配。 我之前的post错误地表示~不能使用索引进行前缀search。 消除了这种差异,确实是否要在可能的情况下坚持符合标准的function。

看这个演示SQLFiddle ; 注意不同的执行计划。 请注意~ '1234.*'~ '^1234.*'之间的区别。

给出样本数据:

 create table test ( blah text ); insert into test (blah) select x::text from generate_series(1,10000) x; create index test_blah_txtpat_idx ON test(blah text_pattern_ops); 

请注意, ~即使它实际上更昂贵(人为地由于enable_seqscan ),也使用enable_seqscan因为它没有别的select,而LIKE使用索引。 然而,一个左锚的修正~使用该指标:

 regress=# SET enable_seqscan = 'f'; SET regress=# explain select 1 from test where blah ~ '12.*'; QUERY PLAN --------------------------------------------------------------------------- Seq Scan on test (cost=10000000000.00..10000000118.69 rows=2122 width=0) Filter: (blah ~ '12.*'::text) (2 rows) regress=# explain select 1 from test where blah like '12%'; QUERY PLAN ------------------------------------------------------------------------------------ Bitmap Heap Scan on test (cost=4.55..46.76 rows=29 width=0) Filter: (blah ~~ '12%'::text) -> Bitmap Index Scan on test_blah_txtpat_idx (cost=0.00..4.54 rows=29 width=0) Index Cond: ((blah ~>=~ '12'::text) AND (blah ~<~ '13'::text)) (4 rows) regress=# explain select 1 from test where blah ~ '^12.*'; QUERY PLAN ------------------------------------------------------------------------------------- Bitmap Heap Scan on test (cost=5.28..51.53 rows=101 width=0) Filter: (blah ~ '^12.*'::text) -> Bitmap Index Scan on test_blah_txtpat_idx (cost=0.00..5.25 rows=100 width=0) Index Cond: ((blah ~>=~ '12'::text) AND (blah ~<~ '13'::text)) (4 rows) 

PostgreSQL中有许多模式匹配运算符 。 LIKESIMILAR TO~在本手册中都有介绍。

如果可以的话,使用LIKE~~ ),这是最快的。
如果你不能,使用正则expression式( ~ ),它更强大。
从来没有用户SIMILAR TO 。 这完全没有意义。 更进一步下来。

安装附加模块pg_trgm也使相似性运算符%可用。

为了使图片完整,也有自己的基础设施的文本search 。

索引支持可用于每个这些运营商 – 在不同程度上。 它经常胜过其他选项的performance。 但是细节上还是有很多的余地,即使有索引。

没有pg_trgm, 左侧的锚定search模式有索引支持。 如果数据库集群以非“C”语言环境运行,则需要具有特殊操作符类的索引,如text_pattern_opsvarchar_pattern_ops 。 是的, 基本的左锚正则expression式也被支持 。 例:

 CREATE TABLE tbl(string text); INSERT INTO tbl(string) SELECT x::text FROM generate_series(1, 10000) x; CREATE INDEX tbl_string_text_pattern_idx ON tbl(string text_pattern_ops); SELECT * FROM tbl WHERE string ~ '^1234'; -- left anchored pattern 

SQL小提琴。

在安装了pg_trgm的情况下,还可以使用运算符类gist_trgm_opsgin_trgm_ops使用GIN或GiST索引。 这些索引可以支持任何 LIKEexpression式,而不仅仅是左锚。 但是,还没有支持正则expression式(除了基本的左锚)。 亚历山大·科罗特科夫和其他人正在研究:

更新 : 在Postgres 9.3中增加了对任意正则expression式匹配的支持,并且自那以后改进了几次。

SIMILAR TO是SQL标准的一部分,但语法非常奇怪,PostgreSQL支持它的唯一原因是遵守标准。 在内部,每个SIMILAR TOexpression式都用正则expression式重写。 因此,对于任何给定的SIMILAR TOexpression式,至less有一个正则expression式可以更快地完成相同的工作。 我从来没有使用SIMILAR TO 。 更多:

  • 在PostgreSQL中与LIKE,SIMILAR TO或正则expression式匹配的模式

~~运算符等同于LIKE~另一方面, 将使用POSIX正则expression式匹配 。

我只是做了一个快速和简单的基准来看看没有涉及到索引时两个运营商之间的性能差异:

 postgres=# \timing Timing is on. postgres=# SELECT count(1) FROM (SELECT val from generate_series(1, 10000000) x(val) WHERE val::text LIKE '%5%') AS x; count ───────── 5217031 (1 row) Time: 5631.662 ms postgres=# SELECT count(1) FROM (SELECT val from generate_series(1, 10000000) x(val) WHERE val::text ~ '5') AS x; count ───────── 5217031 (1 row) Time: 10612.406 ms 

在这个例子中, LIKE运算符几乎是~运算符的两倍。 所以如果速度是关键,我会倾向于LIKE ,尽pipe要小心不要过早优化。 ~给你更多的灵活性。

对于那些有兴趣的人,这里是解释上述查询的计划:

 postgres=# EXPLAIN ANALYZE SELECT count(1) FROM (SELECT val from generate_series(1, 10000000) x(val) WHERE val::text LIKE '%5%') AS x; QUERY PLAN ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Aggregate (cost=20.00..20.01 rows=1 width=0) (actual time=9967.748..9967.749 rows=1 loops=1) -> Function Scan on generate_series x (cost=0.00..17.50 rows=1000 width=0) (actual time=1732.084..7404.755 rows=5217031 loops=1) Filter: ((val)::text ~~ '%5%'::text) Rows Removed by Filter: 4782969 Total runtime: 9997.587 ms (5 rows) postgres=# EXPLAIN ANALYZE SELECT count(1) FROM (SELECT val from generate_series(1, 10000000) x(val) WHERE val::text ~ '5') AS x; QUERY PLAN ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Aggregate (cost=20.00..20.01 rows=1 width=0) (actual time=15118.061..15118.061 rows=1 loops=1) -> Function Scan on generate_series x (cost=0.00..17.50 rows=1000 width=0) (actual time=1724.591..12516.996 rows=5217031 loops=1) Filter: ((val)::text ~ '5'::text) Rows Removed by Filter: 4782969 Total runtime: 15147.950 ms (5 rows) 

是的,它代表POSIX正则expression式。 另一种替代方法是使用“SIMILAR TO”运算符对正则expression式使用SQL标准方法,虽然它提供了一组更为有限的function,但可能更容易理解。 我认为这是一个很好的参考从DBA交stream: https : //dba.stackexchange.com/questions/10694/pattern-matching-with-like-similar-to-or-regular-expressions-in-postgresql