programing

POSTgres에서 LIKE와 ~의 차이

telecom 2023. 5. 15. 21:16
반응형

POSTgres에서 LIKE와 ~의 차이

"당신을 귀찮게 하지 말라"는 지시를 받았어요.LIKE 및사를 합니다.~대신.무슨 문제가 있습니까?LIKE그리고 어떻게 지내십니까?~ 른가요다?

있습니까?~이런 맥락에서 이름을 가지고 있거나 사람들이 "틸드 연산자를 사용한다"고 말합니까?

~는 정규식 연산자이며, 이에 의해 암시되는 기능을 가지고 있습니다.정규식 와일드카드 및 한정자의 전체 범위를 지정할 수 있습니다. 자세한 내용은 설명서를 참조하십시오.그것은 확실히 더 강력합니다.LIKE그리고 그 힘이 필요할 때 사용되어야 하지만, 그들은 다른 목적을 위해 사용됩니다.

에 아무런 문제가 없습니다.LIKE 그고리 IMO, ▁to▁favour▁reason다▁and.~그 위에오히려 그 반대입니다.LIKE SQL 표준입니다.그렇습니다. 하지만 널리 지원되지는 않습니다.포스트그레SQL(또는 posix 정규식 일치 연산자)은 SQL 표준이 아닙니다.

그런 이유로, 저는 사용하는 것을 선호합니다.LIKE▁use곳▁it▁▁only하용▁i▁and내가ive'▁enough오직s.~ 표현힘필이때요할의규한▁it때할요▁databases필▁i. 데이터베이스를 포팅해야 하는 라도 덜 데이터베이스를 포팅해야 하는 경우 하나라도 덜 아플 수 있습니다.제가 사용하는 경향이 있습니다.SIMILAR TO 때에LIKE충분히 강력하지는 않지만, 어윈의 의견 이후에 저는 그것을 그만 하고 사용할 것 같습니다.~ 때에LIKE그 일을 하지 않습니다.

, Postgre.할 수 예: SQL 접 검 예 b-tree 인 스 할 있 습 니 수 다 용 사 를 덱 은 :LIKE 'TEST%')와 함께LIKE또는SIMILAR TO가 이터베에있경에 있는 C에 " " "가 있습니다.text_pattern_ops앞에서 쓴 것과 달리 Pg는 왼쪽 고정된 포식스 정규식에 이러한 인덱스를 사용할 수도 있습니다. 명시적인 '^TEST'만 있으면 됩니다.정규식은 처음부터 일치해야 합니다.아까 제 게시물에는 다음과 같이 잘못 기재되어 있습니다.~접두사 검색에 인덱스를 사용할 수 없습니다.이러한 차이가 사라지면 가능한 한 표준 호환 기능을 고수할지 여부에 따라 결정됩니다.

데모 SQLFidle을 참조하십시오. 다양한 실행 계획을 확인하십시오.사이의 차이에 주목합니다.~ '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);

을 주의하여 보다~비싼 합니다(구체적으로 seqscan 입니다).enable_seqscan에, 에 )는 대안이 없습니다.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)

개요

LIKE,SIMILAR TO그리고.~Postgre의 기본 패턴 매칭 연산자입니다.SQL.

가능하면 ()를 ~~사용하는 것이 가장 빠르고 간단합니다.
그럴 수 없는 경우 정규 ~표현()을 사용하면 더 강력합니다.
사용자 없음 SIMILAR TO 무의미합니다.아래를 참조하십시오.

추가 모듈 pg_trgm을 설치하면 고급 인덱스 옵션과 유사성 연산자가 추가됩니다.
그리고 자체 인프라와 운영자(다른 것들 중)를 사용한 텍스트 검색도 있습니다.

인덱스 지원은 각 연산자에 대해 다양한 수준으로 제공됩니다.정기적으로 다른 옵션의 성능을 능가합니다.하지만 세부적인 부분에는 많은 여유가 있습니다. 심지어 지수도 마찬가지입니다.

인덱스 지원

pg_trgm사용하지 않으면 왼쪽 고정 검색 패턴에 대한 인덱스만 지원됩니다.데이터베이스 클러스터가 C가 아닌 로케일(일반적인 경우)로 실행되는 경우 다음과 같은 특수 연산자 클래스가 있는 인덱스가 필요합니다.text_pattern_ops또는varchar_pattern_ops기본적인 왼쪽 고정 정규식도 이에 의해 지원됩니다.예:

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

db<>여기로 이동

pg_trgm을 설치하면 연산자 클래스에서 GIN 또는 GiST 인덱스를 사용할 수 있습니다.gist_trgm_ops또는gin_trgm_ops이 인덱스는 다음 항목을 지원합니다. LIKE그냥 고정된 상태로 두는 것이 아니라 표현.설명서를 인용하여 설명합니다.

Postgre에서 시작SQL 9.3에서 이러한 인덱스 유형은 정규식과 일치하는 인덱스 검색도 지원합니다.

세부사항:


SIMILAR TO 매우 이상한 구조입니다.포스트그레SQL 표준의 초기 버전에서 정의되었기 때문에 SQL에서만 이를 구현합니다.내부적으로, 모든SIMILAR TO식을 정규식으로 다시 씁니다.그러므로, 어떤 주어진 경우에도.SIMILAR TO식, 동일한 작업을 더 빨리 수행하는 정규식이 하나 이상 있습니다.절대 사용 안 함SIMILAR TO.

자세한 내용:

좋아요는 시작이나 끝 또는 중간 문자열의 일부와 일치합니다. 기울기(~)는 정규식과 일치합니다.

이를 더 설명하기 위해 표를 만들고 몇 가지 값을 삽입합니다.

# create table users(id serial primary key, name character varying);

이제 표에 몇 가지 값을 삽입하겠습니다.

# insert into users (name) VALUES ('Alex'), ('Jon Snow'), ('Christopher'), ('Arya'),('Sandip Debnath'), ('Lakshmi'),('alex@gmail.com'),('@sandip5004'), ('lakshmi@gmail.com');

이제 당신의 테이블은 이 모양이어야 합니다.

 id |       name        
----+-------------------
  1 | Alex
  2 | Jon Snow
  3 | Christopher
  4 | Arya
  5 | Sandip Debnath
  6 | Lakshmi
  7 | alex@gmail.com
  8 | lakshmi@gmail.com
  9 | @sandip5004

케이스 LIKE

# select * from users where name like 'A%';
 id | name 
----+------
  1 | Alex
  4 | Arya
(2 rows)

당신이 볼 수 있듯이.'A%'이름이 대문자 A로 시작하는 값만 얻을 수 있습니다.

# select * from users where name like '%a%';
 id |       name        
----+-------------------
  4 | Arya
  5 | Sandip Debnath
  6 | Lakshmi
  7 | alex@gmail.com
  8 | lakshmi@gmail.com

당신이 볼 수 있듯이.'%a%'이름이 다음과 같은 값만 얻을 수 있습니다.a이름 사이에

# select * from users where name like '%a';

 id | name 
----+------
  4 | Arya

당신이 볼 수 있듯이.'%a'이름이 다음으로 끝나는 값만 얻을 수 있습니다.a.

대소문자 - (기울임)

# select * from users where name ~* 't';
 id |      name      
----+----------------
  3 | Christopher
  5 | Sandip Debnath

당신이 볼 수 있듯이.name ~* 't'이름이 다음과 같은 값만 얻을 수 있습니다.t.~대소문자 구분을 의미하고 ~*는 대소문자 구분을 의미하므로

# select * from users where name ~ 'T';
 id | name 
----+------
(0 rows)

위의 쿼리는 우리에게 0개의 행을 주었습니다.T어떤 항목과도 일치하지 않았습니다.

이제 이메일 ID만 가져오면 되고 메일 ID에 무엇이 있는지 알 수 없지만 이메일 패턴을 알고 있는 경우를 생각해 보겠습니다. 즉, 문자나 숫자 또는 _ 또는 . 또는 -, @, 그 다음에는 더 많은 문자나 숫자 또는 -가 있을 것입니다.com또는in또는org etc정규 표현을 사용하여 패턴을 만들 수 있습니다.

이제 정규식을 사용하여 결과를 가져오도록 하겠습니다.

# select * from users where name ~* '[a-z0-9\.\-\_]+@[a-z0-9\-]+\.[a-z]{2,5}';
 id |       name        
----+-------------------
  7 | alex@gmail.com
  8 | lakshmi@gmail.com

마찬가지로 우리는 사이에 공백이 있는 이름을 가져올 수 있습니다.

#select * from users where name ~* '[a-z]+\s[a-z]+';
 id |      name      
----+----------------
  2 | Jon Snow
  5 | Sandip Debnath

[a-z]+는 a에서 z까지의 문자가 있을 수 있음을 의미하고 +는 1회 이상 발생할 수 있음을 의미하며 \s는 그 사이에 공백이 있다가 다시 1회 이상 발생할 수 있음을 의미합니다.

이 상세한 분석이 도움이 되길 바랍니다.

~~연산자는 다음과 같습니다.LIKE. ~반면에 POSIX 정규식을 사용하여 일치합니다.

인덱스가 포함되지 않은 경우운영자 간의 성능 차이를 살펴보기 위해 빠르고 간단한 벤치마크를 수행했습니다.

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하지만 너무 일찍 최적화하지 않도록 주의해야 합니다. ~유연성이 훨씬 높아집니다.

관심 있으신 분들을 위해, 여기 있습니다.EXPLAIN쿼리에 : " " " 은 다음과 같습니다.

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 regex의 약자입니다.또 다른 대안은 정규식에 대한 SQL 표준 접근 방식을 "유사한 대상" 연산자와 함께 사용하는 것입니다. 더 제한된 기능 집합을 제공하지만 이해하기가 더 쉬울 수 있습니다.저는 이것이 dba exchange의 좋은 참고 자료라고 생각합니다. https://dba.stackexchange.com/questions/10694/pattern-matching-with-like-similar-to-or-regular-expressions-in-postgresql

언급URL : https://stackoverflow.com/questions/12452395/difference-between-like-and-in-postgres

반응형