database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
ㆍPostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
PostgreSQL Q&A 8758 게시물 읽기
No. 8758
query 가 느려서 explain 했는데 seq 스캔을 하는데, 어떻게 해야 하나요??
작성자
김영호(wineoflove)
작성일
2011-01-10 12:01ⓒ
2011-01-10 12:01ⓜ
조회수
9,527

SELECT pa.patientid, st.studyid, st.studydate, se.seriesnumber, im.sopinstanceuid, im.sopclassuid,
im.imagewidth, im.imageheight, im.windowcenter , im.windowwidth, im.desc1, im.desc2, im.annotationdescription , im.filter, im.filename
 FROM patientlevel pa, studylevel st, serieslevel se, imagelevel im
 WHERE pa.patientid='428578'
 AND pa.patientid = st.patientparent_key
 AND st.studyinstanceuid = se.studyparent_key
 AND se.seriesinstanceuid = im.seriesparent_key 
  

 

위와 같은 쿼리가 있습니다.

구조는 patientlevel > studylevel > serieslevel > imagelevel

순으로 조인이 되는 구조 이고,

imagelevel 은 1000만건 정도 데이터가 있고,

나머지는 100만건 이내로 데이터가 있습니다.(피라미드 구조~ ^^)

 

 

어제 저녁

각 테이블을 vacuum analyze 를 돌렸습니다. 이후,

갑자기 쿼리가 느려져서,

explain 을 했더니

 Sort  (cost=2016313.19..2016316.18 rows=1197 width=522) (actual time=896510.838..896511.046 rows=369 loops=1)
   Sort Key: st.studydate, se.seriesnumber, im.imagenumber
   ->  Hash Join  (cost=31111.52..2016251.99 rows=1197 width=522) (actual time=23139.313..896506.779 rows=369 loops=1)
         Hash Cond: (("outer".seriesparent_key)::text = ("inner".seriesinstanceuid)::text)
         ->  Seq Scan on imagelevel im  (cost=0.00..1952962.00 rows=6433300 width=360) (actual time=22028.013..888457.315 rows=6723501 loops=1)
         ->  Hash  (cost=31110.99..31110.99 rows=215 width=215) (actual time=591.677..591.677 rows=0 loops=1)
               ->  Nested Loop  (cost=0.00..31110.99 rows=215 width=215) (actual time=41.263..591.541 rows=31 loops=1)
                     ->  Nested Loop  (cost=0.00..517.45 rows=135 width=144) (actual time=14.431..168.219 rows=20 loops=1)
                           ->  Index Scan using patient_idx on patientlevel pa  (cost=0.00..5.41 rows=1 width=36) (actual time=0.058..0.063 rows=1 loops=1)
                                 Index Cond: ((patientid)::text = '428578'::text)
                           ->  Index Scan using sl_patientid on studylevel st  (cost=0.00..510.69 rows=135 width=118) (actual time=14.348..167.895 rows=20 loops=1)
                                 Index Cond: ((patientparent_key)::text = '428578'::text)
                     ->  Index Scan using srl_uid on serieslevel se  (cost=0.00..225.46 rows=93 width=127) (actual time=20.677..21.144 rows=2 loops=20)
                           Index Cond: (("outer".studyinstanceuid)::text = (se.studyparent_key)::text)
 Total runtime: 896511.606 ms
 

imagelevel 부분을 seq 스캔을 하는데, 어떻게 해야 하나요??

imagelevel에 있는 seriesparent_key 와 조인하는 serieslevel 의 seriesinstanceuid 모두 인덱스는 걸려 있습니다. ㅠ

제 머리로 해볼수 있는 부분들은 모두 시도해보았는데,, 휴,, 전혀 답이 안나와서, 이렇게 문의 드려 봅니다~ 

고수 선생님들의 지도 부탁드리며, 긴글 읽어주셔서 감사드립니다.

 

참고로 DB버전은 8.0.3, CentOS 4.4 에서 구동중에 있습니다.

 

 

이 글에 대한 댓글이 총 3건 있습니다.

저도 예전에 비슷한 경험이 있어서 강제고 seq scan을 못하도록 막아버렷던 적이있습니다 . .

막고난 다음의 효과는 별로  차이가 없었던것 같아야 . . . .

그냥 pgsql을 알아서 똑바로 가고 있겠거니 하고 있습니다 . . .

일단 plan 상에서는 seq scan을 하지는 않을 거예요 . . . ^^

postgresql.conf   에서 . .

 

enable_seqscan = off     <--  이부분을 off 로 해보세요 . .

물론 버젼에 따라서  . . 다르게 적어야 될 수도 있습니다 . . 예를 들면 false 로 . . .

함 해보세요 .. .  ^^

 

롱다리님이 2011-01-10 14:57에 작성한 댓글입니다. Edit

롱다리님 답변 감사 드립니다.

답변해주신 내용대로 적용하여 테스트를 해봤는데~

바로~~~~~~~~~ index scan 하더군요~!

완전 깜짝 놀랐습니다.

 

하지만, 해당 DB내에서 seq scan 이 필요한 경우가 있기도 하여,

postgres.conf 에서 계속 enable_seqscan 값을 off 로 둘수는 없었습니다~

 

하여, 여기서 부터 자답입니다.

index를 타기를 꼭 원하는 부분

(serieslevel 과 imagelevel 의 조인 부분) 의 해당 키 값을

 

alter table 테이블명 alter column 필드명 set statistics 150;

위 쿼리를 날려 변경시켜주고

 

analyze verbose 테이블명

쿼리를 실행시켜 주고 난 이후

 

explain 을 해보면 seq 대신 index를 타는것을 확인 하였습니다~

 

statistics 값은 기본값이 -1인데 -1일때  default_statistics_target 값을 사용하게 됩니다.

(이 값은 보통 10)

 

이값을 20 단위로 증가 시켜가며 explain 결과를 보고 150으로 지정하였습니다~ ^^

아마 케이스별로 저 값을 변화 시켜야 하는것 같습니다~ ㅎㅎ

 

오늘 이거 때문에 postgresql 에는 오라클의 힌트 기능이 없나,, 한참 검색해봤는데,

일단 set statistics 를 이용하면 어느정도 원하는대로 쿼리 실행 계획을 조절할수 있을것 같습니다~

 

김영호(wineoflove)님이 2011-01-10 17:13에 작성한 댓글입니다.

 쿼리를 날리기전에 set enable_indexscan=true; set enable_seqscan=false; 

이렇게 보내신 후에 쿼리 실행하시면 원하시는 결과를 얻으실것입니다. 그럼

 

김병석(byung82)님이 2011-01-14 04:09에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
8761특정테이블 하나만 . . ramdisk에 올려서 사용할 수 있나요 . .. ^^ [1]
롱다리
2011-01-15
7576
8760시스템 이행에 따른 컬럼타입 문제.
슝슝이
2011-01-14
7510
8759가변데이터 처리시 테이블 분할과 배열 처리중 뭐가 더 효율이 좋을까요? [1]
노지석
2011-01-11
7764
8758query 가 느려서 explain 했는데 seq 스캔을 하는데, 어떻게 해야 하나요?? [3]
김영호
2011-01-10
9527
8757쿼리좀 봐주세요..
이기자
2011-01-04
7942
8756pg_hba.conf 설정 관련 [2]
강진묵
2011-01-03
8693
8755PB에서 DB연결후 현재시간 가져오기 [2]
이기자
2010-12-31
8537
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.024초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다