식에서 집계 LIKE 쿼리 속도를 높이기 위해 인덱스를 만드는 방법은 무엇입니까?


20

제목에 잘못된 질문이있을 수 있습니다. 사실은 다음과 같습니다.

Django 기반 사이트의 관리 인터페이스에서 고객 조회를 수행 할 때 고객 서비스 담당자가 응답 시간이 느리다고 불평했습니다.

우리는 Postgres 8.4.6을 사용하고 있습니다. 느린 쿼리 로깅을 시작하고이 범인을 발견했습니다.

SELECT COUNT(*) FROM "auth_user" WHERE UPPER("auth_user"."email"::text) LIKE UPPER(E'%deyk%')

이 쿼리는 실행하는 데 32 초 이상 걸립니다. EXPLAIN에서 제공하는 쿼리 계획은 다음과 같습니다.

QUERY PLAN
Aggregate  (cost=205171.71..205171.72 rows=1 width=0)
  ->  Seq Scan on auth_user  (cost=0.00..205166.46 rows=2096 width=0)
        Filter: (upper((email)::text) ~~ '%DEYK%'::text)

이것은 Django Admin 응용 프로그램에서 생성 된 Django QuerySet에서 Django ORM에 의해 생성 된 쿼리이므로 쿼리 자체를 제어 할 수 없습니다. 색인은 논리적 솔루션처럼 보입니다. 속도를 높이기 위해 색인을 만들려고했지만 차이가 없었습니다.

CREATE INDEX auth_user_email_upper ON auth_user USING btree (upper(email::text))

내가 도대체 ​​뭘 잘못하고있는 겁니까? 이 쿼리 속도를 높이려면 어떻게해야합니까?

답변:


21

왼쪽 고정 검색어를 제외하고 PostgreSQL 8.4 에서 LIKE/ ILIKE에 대한 인덱스 지원은 없습니다 .

PostgreSQL 9.1 부터 추가 모듈 pg_trgm은 GIN 및 GiST 삼각 그램 인덱스 LIKE/ ILIKE정규 표현식 (연산자 ~및 친구)을 위한 연산자 클래스를 제공합니다 . 데이터베이스 당 한 번 설치 :

CREATE EXTENSION pg_trgm;

GIN 지수의 예 :

CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);

관련 :


2
이것은 실제로 정답입니다.
vonPetrushev

9

일치하는 시작시 '%'로 인해 해당 인덱스가 도움이되지 않습니다. BTREE 인덱스는 접두사 만 일치시킬 수 있으며 쿼리 시작시 와일드 카드는 찾을 접두사가 없습니다.

이것이 테이블 스캔을 수행하고 모든 레코드를 쿼리 문자열과 차례로 일치시키는 이유입니다.

현재 LIKE를 사용하여 하위 문자열 검색을 수행하는 대신 전체 텍스트 인덱스와 텍스트 일치 연산자를 사용해야합니다. 문서에서 전체 텍스트 검색에 대한 자세한 내용을 찾을 수 있습니다.

http://www.postgresql.org/docs/8.4/static/textsearch-intro.html

사실 나는 그 페이지에서 LIKE가 색인을 절대 사용하지 않는다는 것을 알았습니다 .BTREE 색인을 사용하여 와일드 카드가 아닌 접두사를 해결할 수 있어야하기 때문에 이상하게 보입니다. 몇 가지 빠른 테스트는 문서가 올바르다는 것을 암시하지만,이 경우 쿼리를 해결하기 위해 LIKE를 사용하는 동안에는 인덱싱 양이 도움이되지 않습니다.


그것이 내가 두려워했던 것입니다. 도움이 될만한 다른 종류의 색인이 있습니까? 내가 말했듯이 쿼리 자체에 영향을 줄 수있는 능력이 약간 제한되어 있습니다.
David Eyk

또한 주요 %기능은 필수 기능입니다. 고객 서비스 담당자는 특히 이메일 주소에 오타가있는 경우 고객 계정을 찾는 데 필요합니다.
David Eyk

LIKE와 전체 텍스트 인덱싱에 대해 약간의 연구를 한 결과, 요점을보기 시작했습니다.
David Eyk

지금은 선행 와일드 카드를 억제하는 방법을 찾았습니다. 그것은 당신이 밝혀 당신이 적절한으로 인덱스를 만들 경우, LIKE와 인덱스를 사용하는 연산자 클래스 . 문서는 여기에 있습니다 : postgresql.org/docs/8.4/static/indexes-opclass.html
David Eyk

또한 부풀어 오르지 않았는지 DB를 확인하십시오. 해당 테이블에 많은 부풀림이있는 경우 스캔하는 데 시간이 오래 걸립니다. 가동 중지 시간이있는 경우 기본 키에서 클러스터링하여 더 빠른지 확인하십시오. 부풀림을 확인하려면 wiki.postgresql.org/wiki/Show_database_bloat 에서 분석을 실행 한 다음 쿼리를 실행할 수 있습니다 . 보다 정확한 값은 해당 페이지의 하단을 참조하십시오.
Scott Marlowe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.