문제

정규 표현식을 열에있는 컬럼의 varchar로 저장 한 것으로, 들어오는 입력과 일치해야합니다.예를 들어, 테이블에는 다음이 포함될 수 있습니다.

| field |     value     |
|-------|---------------|
| email | .*@domain.com |
.

및 쿼리는 다음과 같습니다.

SELECT *
FROM table
WHERE field = 'email'
  AND 'someone@domain.com' ~* value
.

나는 이것이 약 2 년 동안 충분히 잘 어울립니다.테이블은 이제 10K 행을 마인드 샤프트하고 쿼리가 3 초 정도로 느려졌습니다.나는 이미 우리를 훨씬 더 합리적인 전략으로 옮겼 으므로이 질문은 순전히 학문적입니다.

이 설정을 유지하면 조회 효율을 늘릴 수있는 방법이 있습니까?나는 varchar_pattern_ops의 일부 형제를 희망하고 있지만,이 쿼리는 해결되는 것의 반대입니다.


아이디어가 내려 며, 여기에 전체 테이블, 쿼리 및 설명

+------------+-----------------------------+------------------------------------------------------------+
| Column     | Type                        | Modifiers                                                  |
|------------+-----------------------------+------------------------------------------------------------|
| id         | integer                     | not null default nextval('table_id_seq'::regclass)         |
| field      | character varying(255)      | not null                                                   |
| value      | character varying(1000)     | not null                                                   |
| comment    | text                        |                                                            |
+------------+-----------------------------+------------------------------------------------------------+
Indexes:
    "table_pkey" PRIMARY KEY, btree (id)
    "index_table_on_field_and_value" UNIQUE, btree (field, value)


EXPLAIN ANALYZE
SELECT *
FROM table
WHERE (
    (field = 'contact_email' AND 'person@place.com' ~* value)
 OR (field = 'phone'         AND value = '1234567890')
 OR (field = 'unique_id'     AND value = 'abcdef')
);

Seq Scan on table (cost=0.00..613.08 rows=58 width=1) (actual time=744.371..744.371 rows=0 loops=1)
Filter: ((((field)::text = 'contact_email'::text) AND ('person@place.com'::text ~* (value)::text))
      OR (((field)::text = 'phone'::text) AND ((value)::text = '01234567890'::text))              
      OR (((field)::text = 'unique_id'::text) AND ((value)::text = 'abcdef'::text)))             
Rows Removed by Filter: 11643
Total runtime: 744.395 ms
.

도움이 되었습니까?

해결책

짧은 버전 : 아니오.패턴 컬럼을 인덱싱 할 수 있도록 실용적인 방법은 없으므로 "이 평문 이이 패턴 중 하나와 일치합니까"쿼리를 쿼리 할 수 있습니다.

PostgreSQL은 "이해되는"패턴 일치하는 특별한 사용자 정의 색인 유형이 필요합니다.나는 그것이 얼마나 실용적으로 하나를 구현하는지 모르겠지만, 그러한 인덱스에서 얼마를 얻을 수 있는지 알지 못합니다.하나도 없기 때문에 문제는 다소 학문적입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 dba.stackexchange
scroll top