복붙노트

[SQL] 포스트 그레스에서 LIKE와의 차이 ~

SQL

포스트 그레스에서 LIKE와의 차이 ~

내가 대신 ~ "LIKE 귀찮게하지"하고 사용 지시했습니다. LIKE 문제는 어떻게 ~ 다른 무엇입니까?

합니까 ~이 컨텍스트에 이름을하거나 사람들이 "물결표 연산자를 사용하여"말을합니까?

해결법

  1. ==============================

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

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

  2. ==============================

    2.그 위에 ~ 선호하는 이유는, IMO,이 LIKE와 아무것도 잘못이 없으며. 오히려 그 반대. LIKE는 SQL-표준입니다. 그래서 유사한 TO이지만, 널리 지원되지 않습니다. PostgreSQL을의 ~ 연산자 (또는 POSIX 정규 표현식 매칭 연산자) SQL 표준이 아니다.

    그 위에 ~ 선호하는 이유는, IMO,이 LIKE와 아무것도 잘못이 없으며. 오히려 그 반대. LIKE는 SQL-표준입니다. 그래서 유사한 TO이지만, 널리 지원되지 않습니다. PostgreSQL을의 ~ 연산자 (또는 POSIX 정규 표현식 매칭 연산자) SQL 표준이 아니다.

    이러한 이유로, 나는 그것이 표현 충분 LIKE를 사용하는 것을 선호 내가 전체 정규 표현식의 힘을 필요로 할 때 난 단지 ~ 사용합니다. 내가 포트 데이터베이스에 필요한 경우 상처 것 하나 적은 것입니다. 내가 좋아하는 강력한 부족이없는 경우 유사한 제품에를 사용하는 경향했지만, 어윈의 발언 이후 나는 내가하고 중단됩니다 생각하고 사용 ~ LIKE이 일을하지 않습니다.

    데이터베이스가 C 로케일 또는 인덱스 text_pattern_ops있는 경우 또한 PostgreSQL을는 B- 트리 등으로 프리픽스 검색 용 인덱스 (예 LIKE '테스트 %') 또는 유사한 대상을 사용할 수있다. 내가 이전에 쓴, 대학원도 왼쪽 고정 된 POSIX 정규식에 대한 이러한 인덱스를 사용할 수는 달리, 그냥 필요가 명시 적으로 '^ TEST. *'정규식은 처음부터 일치 할 수 있도록. 내 게시물 이전 잘못 ~ 접두사 검색을위한 인덱스를 사용할 수 없다고 말했다. 그 차이는 제거로 그것은 진짜로 당신이 수 여부를 경우 표준 준수 기능에 충실 할 것인지 여부에있다.

    이 데모 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);
    

    참고이 대안이 없기 때문에 LIKE는 인덱스를 사용하면서, (enable_seqscan하기 위해 인위적 그렇게 때문에) 더 비싼 실질적 때 ~이 seqscan도를 사용하는. 그러나,이 왼쪽 앵커가 너무 인덱스를 사용하여 ~ 수정 :

    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)
    
  3. ==============================

    3.LIKE, SIMILAR TO와 ~ PostgreSQL의에서 기본 패턴 매칭 연산자입니다.

    LIKE, SIMILAR TO와 ~ PostgreSQL의에서 기본 패턴 매칭 연산자입니다.

    당신이 LIKE을 (~~)를 사용할 수없는 경우, 가장 빠르고 간단합니다. 당신이 정규 표현식 (~)를 사용할 수없는 경우, 그것은 더 강력한입니다. 절대로 사용자 유사한 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
    

    SQL 바이올린.

    pg_trgm가 설치된, GIN 또는 GIST 인덱스 연산자 클래스 gist_trgm_ops 또는 gin_trgm_ops 가능하다. 이 인덱스는 LIKE 표현, 바로 왼쪽에 고정하지를 지원합니다. 그리고, 설명서를 인용 :

    세부:

    유사한 제품에 매우 이상한 구조입니다. 이 SQL 표준의 초기 버전에 정의되어 있기 때문에 PostgreSQL은 단지 그것을 구현합니다. 내부적으로 모든 유사한 TO 표현식은 정규 표현식으로 다시 작성됩니다. 따라서, 주어진 유사한 TO 표현을 위해, 빠른 동일한 일을하고 적어도 하나의 정규 표현식이있다. 나는 유사한 제품에 사용하지 않습니다.

    추가 읽기 :

  4. ==============================

    4.~ 연산자 LIKE 동일하다. ~, 다른 한편으로는, POSIX 정규 표현식을 사용하여 일치합니다.

    ~ 연산자 LIKE 동일하다. ~, 다른 한편으로는, POSIX 정규 표현식을 사용하여 일치합니다.

  5. ==============================

    5.어떤 인덱스가 포함되지 않은 경우 그냥 두 사업자 사이의 성능 차이를보고 빠르고 간단한 벤치 마크를했다 :

    어떤 인덱스가 포함되지 않은 경우 그냥 두 사업자 사이의 성능 차이를보고 빠르고 간단한 벤치 마크를했다 :

    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 향하다 것이 본질이다. ~ 당신에게 많은 더 많은 유연성을 제공합니다.

    관심있는 분들을 위해, 여기에 위의 쿼리의 계획을 설명입니다 :

    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)
    
  6. ==============================

    6.예, POSIX 정규식을 의미합니다. 또 다른 대안은 기능보다 제한된 집합을 제공하지만 이해하기 쉬울 수 있습니다, "유사한 TO"연산자와 정규 표현식에 SQL 표준 접근 방식을 사용하는 것입니다. 나는이 DBA 교환에서 좋은 참고 생각 : https://dba.stackexchange.com/questions/10694/pattern-matching-with-like-similar-to-or-regular-expressions-in-postgresql

    예, POSIX 정규식을 의미합니다. 또 다른 대안은 기능보다 제한된 집합을 제공하지만 이해하기 쉬울 수 있습니다, "유사한 TO"연산자와 정규 표현식에 SQL 표준 접근 방식을 사용하는 것입니다. 나는이 DBA 교환에서 좋은 참고 생각 : https://dba.stackexchange.com/questions/10694/pattern-matching-with-like-similar-to-or-regular-expressions-in-postgresql

  7. ==============================

    7.같은 단지 시작 또는 끝 또는 중간에 두 문자열의 일부를 일치한다 그리고 틸트 (~)는 정규 표현식과 일치한다

    같은 단지 시작 또는 끝 또는 중간에 두 문자열의 일부를 일치한다 그리고 틸트 (~)는 정규 표현식과 일치한다

    의 테이블을 만들고이 더하자를 설명하고 일부 값을 삽입하려면

    # 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
    
    # 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
    

    당신이 볼 수 있듯이 '% %'단지 우리에게 이름이 이름 사이에가있는 값을 얻을 것이다.

    # select * from users where name like '%a';
    
     id | name 
    ----+------
      4 | Arya
    

    당신이 볼 수 있듯이 '%는'단지 우리에게 이름이 끝나는으로 값을 얻을 것이다.

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

    당신이 이름 ~ * 't'를 볼 수 있듯이 단지 우리에게 이름이 t을 가지고있는 값을 얻을 것이다. ~ 수단 대소 문자를 구분하고 ~ * 수단의 대소 문자 구분 그래서

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

    T는 모든 항목과 일치하지 않는되었을 때 위의 쿼리는 우리에게 0 행을 준

    이제 _의 우리는 전자 메일 ID를 가져 오기 위해 필요한 경우를 고려하고 우리가 메일 ID를 가지고있는 모르지만, 우리는 약간의 문자 나 숫자 또는이있을 것이다 이메일 즉의 패턴을 알려 나. 또는 - 다음 @ 다음 좀 더 문자 나 숫자 또는 - 다음. 다음 COM이나 또는 조직 등 우리가 정규 표현식을 사용하여 패턴을 만들 수 있습니다.

    지금하자 정규 표현식을 사용하여 결과를 가져 오기 위해 시도

    # 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
    

    [AZ] + 수단 Z까지 모든 문자가있을 수 있으며, 발생 문자의 집합을 다시 다음 사이에 공간이되도록 한 후 + 수단은 1 회 이상 및 \의 수단을 발생할 수있는 1 이상의 타임스.

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

  8. from https://stackoverflow.com/questions/12452395/difference-between-like-and-in-postgres by cc-by-sa and MIT license