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 6302 게시물 읽기
No. 6302
쿼리 속도 향상 방법 좀 알려주세요...
작성자
장창원
작성일
2005-09-01 13:58
조회수
3,473

안녕하세요. 최근에 postgreSQL 을 알게 되어서, 공부하고 있는 중입니다.

이전에 는 mssql 을 사용했었거든요. 근데, 게시판 문서를 이리저리 살펴보다 보니 mssql 은 대충 설정해도 속도가 나오는데, postgresSQL 은 속도가 잘 안나온다는 내용이 있었습니다. 저도 비슷한 문제가 있어서 도움을 부탁드립니다.

테스트를 위해 mssql 에서 사용하던 자료를 모두 postgreSQL 로 복사했습니다. 자료구조와 데이타 인덱스를 모두 동일하게 작성하고 세개의 테이블에 inner join, outer join 이 있는 쿼리를 실행시켰는데, mssql 은 10초 정도, postgreSQL 은 한참을 기다려도 답이 나오지 않습니다. 자세한 설명을 위해 인덱스와 자료크기 및 쿼리, 쿼리플랜을 같이 적습니다.

 

테이블 medshe1

- 칼럼 76개

- 레코드수 231,803 줄

- pk : pk_medshe1 : cChungnum char(10), cIlyun char(5)

- index : medshe1_jinyymm : cJinyymm char(6)

테이블 medshe4

- 칼럼 41개

- 레코드 수 2,421,845 개

- pk : pk_medshe4 : cChungnum char(10), cIlyun char(5), snLine integer

- index : medshe4_code : cGubun, cCode

medshe4_cost : dCost

medshe4_hang : cHang, cMok

medshe4_jh : cJH

테이블 medrlt3

- 칼럼 13개

- 레코드수 49331 개

- index : medrlt3_chungnum : cChungnum, cIlyun, snLine

medrlt3_jubsunum : cJubsunum

medrlt3_simsa : cSimsa, cJubsunum, cMukem, cIlyun, snLine

쿼리

Select *
From Medshe1 m1,
medshe4 m4
Left outer join medrlt3 t3 on m4.cChungnum=t3.cChungnum and m4.cIlyun=t3.cIlyun and

m4.snLine=t3.snLine
Where m1.cJinyymm='200502' and m1.cChungnum=m4.cChungnum and m1.cIlyun=m4.cIlyun
limit 10

 

쿼리플랜

Limit (cost=0.00..2009.16 rows=10 width=1459)
-> Merge Join (cost=0.00..5267626.67 rows=26218 width=1459)
Merge Cond: (("outer".cchungnum = "inner".cchungnum) AND ("outer".cilyun = "inner".cilyun))
-> Merge Left Join (cost=0.00..4621681.45 rows=2421845 width=708)
Merge Cond: (("outer".cchungnum = "inner".cchungnum) AND ("outer".cilyun = "inner".cilyun) AND ("outer".snline = "inner".snline))
-> Index Scan using pk_medshe4 on medshe4 m4 (cost=0.00..4598227.84 rows=2421845 width=601)
-> Index Scan using medrlt3_chungnum on medrlt3 t3 (cost=0.00..4876.19 rows=49331 width=107)
-> Index Scan using pk_medshe1 on medshe1 m1 (cost=0.00..84575.49 rows=3499 width=751)
Filter: (cjinyymm = '200502'::bpchar)

* limit 는 붙였을때나 없을때나 플랜상의 limit (cost .....) 부분 말고는 똑같습니다.

 

시스템

- cpu p4 2.4Ghz / memory 1Gbyte

- DB 파일이 있는 하드디스크 19Gbyte 에 남은공간 8Gbyte

* 성능 테스트를 위해 mssql 과 같은 드라이브에 db 파일을 두었습니다.

 

postgresSQL.conf 중 기본에서 설정바꾼 부분

....

# - Memory -

shared_buffers = 15000 # min 16, at least max_connections*2, 8KB each
work_mem = 524288 # min 64, size in KB
maintenance_work_mem = 131072 # min 1024, size in KB
max_stack_depth = 2048 # min 100, size in KB
.....

# - Planner Method Configuration -

enable_hashagg = false
enable_hashjoin = false
enable_indexscan = true
enable_mergejoin = true
enable_nestloop = true
enable_seqscan = true
enable_sort = false
enable_tidscan = false
.....

이상입니다.

 

쿼리 플랜으로 볼때는 결과가 금방 나와야 할것 같은데, 우찌해서 답이 안나오는지 모르겠습니다.

쿼리를 실행시키면, cpu 나 메모리는 별로 안쓰는데, 하드디스크를 무지하게 읽습니다.

결과집합이 큰 쿼리일 경우 레코드셋을 가져오는데만도 많은 시간이 걸리는 것 같습니다. 특정 쿼리에서 limit 1 을 끝에 붙이면 금방 끝나는데, 없을 경우에는 한참이 걸립니다.

참고로 저는 mssql 도 오래 썼고, 오라클도 2년 정도 사용했습니다. 이렇게 헤멘적이 없거든요 ^^;;

인덱스는 쿼리에 맞게 걸었다고 생각이 드는데, 뭐가 문제인지 모르겠습니다.

누가 저의 무식을 좀 지적해 주세요...ㅠㅠ;;

도움 부탁드립니다. 감사합니다.

 

 

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

medshe4 테이블의 많은 자료가 윗 쿼리에서 전부 조회되나봅니다.

medshe4 테이블 자료에서  인덱스를 사용해서 필요한 자료만 뽑는 어떤 작업이 사이에 있어야할 것 같네요.

 

김상기(ioseph)님이 2005-09-01 14:22에 작성한 댓글입니다.

답변 감사합니다.

medshe4 테이블의 cChungnum, cIlyun 칼럼에 인덱스가 걸려있고, 이 칼럼으로 조회가 되는데도, 그런식으로 전체 테이블이 검색되는 겁니까? 구체적으로 어떤 처리를 해야 하는지 궁금합니다.

장창원님이 2005-09-01 14:37에 작성한 댓글입니다. Edit

'무식' 이라뇨.. 질문을 보니 전혀 아닌 것 않은데요?

저도 늘 같은 문제로 고민하고 고생도 많이하지만 여기서 도움을 얻어 해결하곤 합니다.

 

글을 보고 몇가지 생각나는 것이 있네요.

 

1) analyze는 하셨나요? analyze 명령이나 vacuum analyze 명령으로 말이죠. 자료가 다량으로 입력이 되었다면 반드시 analyze를 해줘야 query planer가 바른 처리를 합니다. 제가 짐작하기에는 이미 하셨을 듯 하네요.

 

2) 왜 hashage와 hashjoin을 false로 설정하셨나요? merge join 보다는 hash join이 더 효과적이라고 알고 있습니다. enable_sort, enable_tidscan도 true로 하시는 것이 좋을 것 같습니다. 디버깅용이 아닌이상 필요 없을 듯 합니다.

 

3) random_page_cost는 몇으로 하셨나요? 이 숫자를 2.5에서 3 사이로 맞춰보세요. 하드가 하나이니 3 정도가 좋을 것 같습니다. 이 숫자가 낮을 수록 index를 사용할 가능성이 높아집니다. index를 사용하면 index와 table 양쪽에 IO가 발생하기 때문에 하드가 느리거나 얻어지는 결과가 많을 경우에는 seq scan보다 느려집니다. 이 설정은 IO가 얼마나 빠른지를 DB에 알려주는 역할을 하는데 기본 값은 사실 요즘 사용되는 하드 디스크 속도에 비하면 아주 보수적인 값이라고 하더군요. 하지만 아주 빠른 raid가 아닌 이상 2.5 이하로는 내려가지 말라고 합니다. 무조건 인덱스를 쓰는 것이 좋지는 않으니까요.

 

4) explain 말고 explain analyze로 결과를 보여주세요. explain은 쿼리 플레너가 자신이 가지고 있는 통계로 가상의 비용을 계산한 것이구요. explain analyze는 실제로 쿼리를 실행해서 걸린 시간을 보여줍니다.

박성철(gyumee)님이 2005-09-01 16:28에 작성한 댓글입니다.
이 댓글은 2005-09-01 16:40에 마지막으로 수정되었습니다.

 

답변 정말 감사합니다. 제가 파견나갔다가 돌아오는 관계로 어수선해서 답변 확인이 늦었습니다. 말씀하신 내용은 모두 적용해 봤구요, 속도 향상이 좀 있었습니다. 감사합니다.
장창원(cybodime)님이 2005-09-27 15:04에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
6305다중 IP를 사용하는 시스템에서 pgsql연결.. [4]
이현순
2005-09-05
2440
6304rowacount와 동일한 명령어 아시는분 좀 가르쳐 주세요... [5]
이정호
2005-09-03
2257
6303initdb 질문입니다. [1]
김종섭
2005-09-02
1893
6302쿼리 속도 향상 방법 좀 알려주세요... [4]
장창원
2005-09-01
3473
6301autovacuum과 크론으로 돌리기.. [1]
신기배
2005-08-31
2658
6300날짜쿼리를 만들고 있는데..잘 확인이 안됩니다. 꼭좀 바주세요 [3]
사랑다섯
2005-08-31
2172
6299statement_timeout 의 조건과 효과를 알고 싶습니다. [2]
송효진
2005-08-30
2212
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.025초, 이곳 서비스는
	PostgreSQL v16.4로 자료를 관리합니다