Postgres 9.1 데이터베이스 table1
에는 ~ 1.5M 개의 행과 열 label
(이 질문을 위해 단순화 된 이름) 이있는 테이블 이 있습니다.
기능적인 trigram-index가 있습니다 lower(unaccent(label))
( 색인에서 unaccent()
사용할 수 있도록 불변이되었습니다).
다음 쿼리는 매우 빠릅니다.
SELECT count(*) FROM table1
WHERE (lower(unaccent(label)) like lower(unaccent('%someword%')));
count
-------
1
(1 row)
Time: 394,295 ms
그러나 다음 쿼리는 느립니다.
SELECT count(*) FROM table1
WHERE (lower(unaccent(label)) like lower(unaccent('%someword and some more%')));
count
-------
1
(1 row)
Time: 1405,749 ms
검색이 더 엄격하더라도 더 많은 단어를 추가하면 속도가 더 느려집니다.
첫 번째 단어에 대한 하위 쿼리를 실행 한 다음 전체 검색 문자열로 쿼리를 실행하는 간단한 트릭을 시도했지만 쿼리 계획자가 내 기계 작업을 통해 보았습니다.
EXPLAIN ANALYZE
SELECT * FROM (
SELECT id, title, label from table1
WHERE lower(unaccent(label)) like lower(unaccent('%someword%'))
) t1
WHERE lower(unaccent(label)) like lower(unaccent('%someword and some more%'));
table1의 비트 맵 힙 스캔 (비용 = 16216.01..16220.04 행 = 1 너비 = 212) (실제 시간 = 1824.017..1824.019 행 = 1 루프 = 1) Cond를 다시 확인하십시오 : ((lower (unaccent ((label) :: text)) ~~ '% someword %':: text) AND (lower (unaccent ((label) :: text)) ~~ '% someword 그리고 더 많은 %'::본문)) -> table1_label_hun_gin_trgm의 비트 맵 인덱스 스캔 (비용 = 0.00..16216.01 행 = 1 너비 = 0) (실제 시간 = 1823.900..1823.900 행 = 1 루프 = 1) 인덱스 조건 : ((낮은 (unccent ((label) :: text)) ~~ '% someword %':: text) AND (낮은 (unaccent ((label) :: text)) ~~ '% someword 및 더 많은 것 %'::본문)) 총 런타임 : 1824.064ms
내 궁극적 인 문제는 검색 문자열이 웹 인터페이스에서 제공되어 상당히 긴 문자열을 보낼 수 있으므로 상당히 느리고 DOS 벡터를 구성 할 수 있다는 것입니다.
그래서 내 질문은 :
- 쿼리 속도를 높이는 방법?
- 더 빨리 하위 쿼리로 나누는 방법이 있습니까?
- 아마도 Postgres의 이후 버전이 더 좋을까요? (9.4를 시도했는데 더 빨리 보이지 않습니다. 여전히 같은 효과입니다. 이후 버전일까요?)
- 다른 인덱싱 전략이 필요할 수 있습니까?
unaccent
불변 이라고 선언했다 . 나는 이것을 질문에 추가했다.
unaccent
모듈 을 업데이트하면 해킹을 덮어 씁니다 . 대신 함수 래퍼를 제안하는 이유 중 하나입니다.
unaccent()
추가 모듈에서도 제공되며 Postgres는 기본적으로 함수에 대한 인덱스를 지원 하지 않으므로 언급 하지 않아야 합니다IMMUTABLE
. 당신은 무언가를 변경 했어야하고 당신은 당신의 질문에서 정확히 무엇을했는지 언급해야합니다. 내 조언 : stackoverflow.com/a/11007216/939860 . 또한 트라이 그램 인덱스는 대소 문자를 구분하지 않고 일치하는 기능을 지원합니다.WHERE f_unaccent(label) ILIKE f_unaccent('%someword%')
일치하는 색인을 사용하여 다음을 단순화 할 수 있습니다 . 세부 사항 : stackoverflow.com/a/28636000/939860 .