LIMIT의 느린 주문


11

이 쿼리가 있습니다.

SELECT * 
FROM location 
WHERE to_tsvector('simple',unaccent2("city"))
   @@ to_tsquery('simple',unaccent2('wroclaw')) 
order by displaycount

나는 그것에 만족합니다 :

"Sort  (cost=3842.56..3847.12 rows=1826 width=123) (actual time=1.915..2.084 rows=1307 loops=1)"
"  Sort Key: displaycount"
"  Sort Method: quicksort  Memory: 206kB"
"  ->  Bitmap Heap Scan on location  (cost=34.40..3743.64 rows=1826 width=123) (actual time=0.788..1.208 rows=1307 loops=1)"
"        Recheck Cond: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
"        ->  Bitmap Index Scan on location_lower_idx  (cost=0.00..33.95 rows=1826 width=0) (actual time=0.760..0.760 rows=1307 loops=1)"
"              Index Cond: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
"Total runtime: 2.412 ms"

그러나 LIMIT를 추가하면 실행 시간이 2 초 이상 걸립니다.

SELECT * 
FROM location 
WHERE to_tsvector('simple',unaccent2("city"))
   @@ to_tsquery('simple',unaccent2('wroclaw')) 
order by displaycount 
limit 20

설명:

"Limit  (cost=0.00..1167.59 rows=20 width=123) (actual time=2775.452..2775.643 rows=20 loops=1)"
"  ->  Index Scan using location_displaycount_index on location  (cost=0.00..106601.25 rows=1826 width=123) (actual time=2775.448..2775.637 rows=20 loops=1)"
"        Filter: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
"Total runtime: 2775.693 ms"

ORDER BY 및 LIMIT에 문제가 있다고 생각합니다. PostgreSQL이 인덱스를 사용하고 마지막에 순서를 지정하도록하려면 어떻게해야합니까?

하위 쿼리는 도움이되지 않습니다.

SELECT * 
FROM (
    SELECT * 
    FROM location 
    WHERE to_tsvector('simple',unaccent2("city"))
       @@ to_tsquery('simple',unaccent2('wroclaw')) 
    order by displaycount
) t 
LIMIT 20;

또는:

SELECT * 
FROM (
    SELECT * 
    FROM location 
    WHERE to_tsvector('simple',unaccent2("city"))
       @@ to_tsquery('simple',unaccent2('wroclaw'))
) t 
order by displaycount 
LIMIT 20;

답변:


12

내 생각에 이것이 쿼리를 수정하는 것입니다.

SELECT * 
FROM   location 
WHERE     to_tsvector('simple',unaccent2(city))
       @@ to_tsquery('simple',unaccent2('wroclaw')) 
ORDER  BY to_tsvector('simple',unaccent2(city))
       @@ to_tsquery('simple',unaccent2('wroclaw')) DESC
         ,displaycount 
LIMIT  20;

나는 논리적으로 중복되는 절의 WHERE첫 번째 요소로 조건을 반복 ORDER BY하지만 쿼리 플래너가 인덱스에 따라 행을 처리하는 것이 더 나을 것이라고 가정하지 않아야합니다. location_displaycount_index이는 훨씬 더 비쌉니다.

근본적인 문제는 쿼리 플래너가 WHERE조건 의 선택성 및 / 또는 비용을 분명히 잘못 판단한다는 것 입니다. 왜 그런지 추측 할 수 있습니다.

당신이 있습니까 자동 진공 있는도 실행하는주의해야 - 실행 ANALYZE하여 테이블에? 따라서 테이블 통계가 최신입니까? 당신이 실행하면 모든 효과 :

ANALYZE location;

그리고 다시 시도 하시겠습니까?

또한 @@작업자 의 선택성 이 잘못 판단 될 수 있습니다 . 논리적 인 이유로 추정하기가 매우 어렵다고 생각합니다.


내 쿼리로 문제를 해결하지 못하고 일반적으로 기본 이론을 확인하려면 다음 두 가지 중 하나를 수행하십시오 .

후자는 덜 방해적이고 현재 세션에만 영향을 미칩니다. 더 빠른 계획에 사용되는 메소드 bitmap heap scanbitmap index scan열린 상태를 유지합니다 .
그런 다음 쿼리를 다시 실행하십시오.

BTW : 이론이 튼튼하다면, FTS 조건에서 선택적인 검색어가 적어 질수록 (현재와 마찬가지로) 쿼리 속도가 훨씬 빨라집니다. 시도 해봐.


1
쿼리가 작동합니다. 인덱스 스캔을 끄면 작동합니다. ANALYZE가 작동하지 않습니다. 포괄적 인 답변에 감사드립니다.
ziri

0

LIMIT postgresql을 사용할 때 행의 하위 집합 만 검색하는 것이 가장 적합합니다. 불행히도 그것은 어떻게 든 귀하의 경우에 잘못된 선택을합니다. 테이블 통계가 너무 오래 되었기 때문일 수 있습니다. VACUUM ANALYZE 위치를 발행하여 통계를 업데이트하십시오.

색인 사용은 일반적으로 순차적 스캔 사용을 허용하지 않고 수행됩니다 (set enable_seqscan = false 설정). 그러나 귀하의 경우 순차적 스캔을 수행하지 않고 LIMIT를 사용하는 쿼리에 대해 다른 색인으로 전환합니다.

분석이 도움이되지 않는 경우 사용중인 postgresql 버전을 알 수 있습니까? 또한 테이블에 몇 개의 행이 있습니까?


분석은 도움이되지 않았습니다. 테이블에는 약 36000 개의 행이 있으며 postgresql 9.1을 사용하고 있습니다.
ziri
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.