2011-08-25 9 views
0

나는 그러한 쿼리를 가지고 있으며 그것을 최적화하려고합니다. 수행하는데 약 1 초가 걸립니다. 그것은 초당 몇 번 실행되기 때문에 어떻게 든 성능 병목 현상입니다. 여기PostgreSQL 쿼리 최적화

는 쿼리입니다 :

SELECT "spoleczniak_tablica"."id", "spoleczniak_tablica"."postac_id", 
"spoleczniak_tablica"."hash", "spoleczniak_tablica"."typ", 
"spoleczniak_tablica"."ikona", "spoleczniak_tablica"."opis", 
"spoleczniak_tablica"."cel", "spoleczniak_tablica"."data", "postac_postacie"."id", 
"postac_postacie"."user_id", "postac_postacie"."avatar", "postac_postacie"."ikonka", 
"postac_postacie"."imie", "postac_postacie"."nazwisko", "postac_postacie"."pseudonim", 
"postac_postacie"."plec", "postac_postacie"."wzrost", "postac_postacie"."waga", 
"postac_postacie"."ur_tydz", "postac_postacie"."ur_rok", "postac_postacie"."ur_miasto_id", 
"postac_postacie"."akt_miasto_id", "postac_postacie"."kasa", "postac_postacie"."punkty", 
"postac_postacie"."zmeczenie", "postac_postacie"."zdrowie", "postac_postacie"."kariera" 
FROM "spoleczniak_tablica" INNER JOIN "postac_postacie" ON 
("spoleczniak_tablica"."postac_id" = "postac_postacie"."id") WHERE 
spoleczniak_tablica.postac_id = 1 or spoleczniak_tablica.id in(select wpis_id from 
spoleczniak_oznaczone where etykieta_id in(select tag_id from spoleczniak_subskrypcje where 
postac_id = 1)) or (spoleczniak_tablica.postac_id in(select obserwowany_id from 
spoleczniak_obserwatorium where obserwujacy_id = 1) and hash not in('dyskusja', 'kochanie', 
'szturniecie')) or (spoleczniak_tablica.cel = 1 and spoleczniak_tablica.hash in('dyskusja', 
'kochanie', 'obserwatorium', 'szturchniecie')) or spoleczniak_tablica.hash = 
'administracja-info' or exists(select 1 from spoleczniak_komentarze where kredka_id = 
spoleczniak_tablica.id and postac_id = 1) ORDER BY "spoleczniak_tablica"."id" DESC LIMIT 
21; 

을 그리고 여기에 ANALYZE EXPLAIN : 나는 ORDER BY를 삭제하면

Limit (cost=52.80..184755.97 rows=21 width=282) (actual time=80.637..229.161 rows=21 loops=1) 
    -> Nested Loop (cost=52.80..27584240184.45 rows=3136216 width=282) (actual time=80.637..229.153 rows=21 loops=1) 
     -> Index Scan Backward using spoleczniak_tablica_pkey on spoleczniak_tablica (cost=52.80..27583220399.44 rows=3136216 width=193) (actual time=80.620..228.767 rows=21 loops=1) 
       Filter: ((postac_id = 1) OR (SubPlan 1) OR ((hashed SubPlan 2) AND ((hash)::text <> ALL ('{dyskusja,kochanie,szturniecie}'::text[]))) OR ((cel = 1) AND ((hash)::text = ANY ('{dyskusja,kochanie,obserwatorium,szturchniecie}'::text[]))) OR ((hash)::text = 'administracja-info'::text) OR (alternatives: SubPlan 3 or hashed SubPlan 4)) 
       SubPlan 1 
       -> Materialize (cost=13.22..11858.79 rows=1255820 width=4) (actual time=0.008..0.044 rows=486 loops=1517) 
         -> Nested Loop (cost=13.22..673.69 rows=1255820 width=4) (actual time=11.818..14.028 rows=486 loops=1) 
          -> HashAggregate (cost=5.89..5.90 rows=1 width=4) (actual time=0.051..0.056 rows=7 loops=1) 
            -> Index Scan using spoleczniak_subskrypcje_postac_id on spoleczniak_subskrypcje (cost=0.00..5.88 rows=2 width=4) (actual time=0.022..0.046 rows=7 loops=1) 
             Index Cond: (postac_id = 1) 
          -> Bitmap Heap Scan on spoleczniak_oznaczone (cost=7.33..662.99 rows=384 width=8) (actual time=1.708..1.978 rows=69 loops=7) 
            Recheck Cond: (etykieta_id = spoleczniak_subskrypcje.tag_id) 
            -> Bitmap Index Scan on spoleczniak_oznaczone_etykieta_id (cost=0.00..7.23 rows=384 width=0) (actual time=1.694..1.694 rows=69 loops=7) 
             Index Cond: (etykieta_id = spoleczniak_subskrypcje.tag_id) 
       SubPlan 2 
       -> Index Scan using spoleczniak_obserwatorium_obserwujacy_id on spoleczniak_obserwatorium (cost=0.00..39.53 rows=21 width=4) (actual time=0.041..0.192 rows=26 loops=1) 
         Index Cond: (obserwujacy_id = 1) 
       SubPlan 3 
       -> Bitmap Heap Scan on spoleczniak_komentarze (cost=18.63..20.64 rows=1 width=0) (never executed) 
         Recheck Cond: ((kredka_id = spoleczniak_tablica.id) AND (postac_id = 1)) 
         -> BitmapAnd (cost=18.63..18.63 rows=1 width=0) (never executed) 
          -> Bitmap Index Scan on spoleczniak_komentarze_kredka_id (cost=0.00..2.98 rows=24 width=0) (never executed) 
            Index Cond: (kredka_id = spoleczniak_tablica.id) 
          -> Bitmap Index Scan on spoleczniak_komentarze_postac_id (cost=0.00..15.40 rows=885 width=0) (never executed) 
            Index Cond: (postac_id = 1) 
       SubPlan 4 
       -> Index Scan using spoleczniak_komentarze_postac_id on spoleczniak_komentarze (cost=0.00..1616.70 rows=885 width=4) (actual time=0.044..54.812 rows=3607 loops=1) 
         Index Cond: (postac_id = 1) 
     -> Index Scan using postac_postacie_pkey on postac_postacie (cost=0.00..0.31 rows=1 width=89) (actual time=0.012..0.014 rows=1 loops=21) 
       Index Cond: (id = spoleczniak_tablica.postac_id) 

는, 쿼리가 2-3 밀리이 필요합니다. 어떤 제안?

+2

3082289 개의 행을 정렬합니다. 너무 오래 걸린다. 임시 테이블을 사용하여 선택한 데이터의 양을 줄이는 것이 좋습니다. 주문하지 않고 'ANALYZE' 출력을 올리시겠습니까? – J0HN

+0

정렬이 표시되지 않습니다. 21 개의 레코드가 허용 될 때까지 인덱스를 사용하고 거꾸로 계산하는 것처럼 보입니다. 필터가 얼마나 선택적인지보기 위해서는'EXPLAIN ANALYZE'가 필요합니다. 즉, 중첩 된 subselect 대신 조인을 사용하려면'etykieta_id'가 포함 된 필터 절을 다시 작성하려고합니다. –

+0

EXPLAIN ANALYZE로 질문을 업데이트했습니다. – ThomK

답변

0

여기에서 실제로 수행해야 할 첫 번째 작업은이 쿼리를보다 쉽게 ​​읽을 수 있도록 다시 디자인하는 것입니다. 그것은 하위 선택을 조인으로 이동시키는 것을 의미합니다.

설명 출력을 읽는 것으로부터 두 번째로 떠오르는 것은 계획자가 실제로 얻는 것보다 더 많은 행을 가정한다는 것입니다. 이로 인해 불필요하게 실현 될 수 있습니다. 여기서해야 할 중요한 일은 관련 테이블의 통계 목표를 늘리고 데이터베이스 분석을 다시 실행하는 것입니다.

이렇게 말하면 21 개가 넘지 않는다는 것을 알고 많은 행을 계획하고있는 이유는 무엇입니까? 이것은 나에게 플래너 제한과 같은 끔찍한 것을 보이고 더 최근의 PostgreSQL 버전으로 업그레이드하면 문제가 해결 될 수 있습니다.