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 6414 게시물 읽기
No. 6414
어찌하면 빨라질까요? 인덱스를 안쓰는거 같은데...
작성자
김이수(isukim)
작성일
2005-11-11 20:42ⓒ
2005-11-11 20:48ⓜ
조회수
4,070

우선 설치환경은

OS : W2K

PostgreSQL : win용 8.0.3

postgresql.conf 설정내용 : 이건 DSN을 찾아보고 했는데 윈도우용을 설치하고나면

Planner Method Configuration와 Planner Cost Constants 는 전부 #으로 막혀있더군요.

# - Planner Method Configuration -

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

# - Planner Cost Constants -

#effective_cache_size = 1000 # typically 8KB each
random_page_cost = 3 # units are one sequential page fetch cost
#cpu_tuple_cost = 0.01 # (same)
#cpu_index_tuple_cost = 0.001 # (same)
#cpu_operator_cost = 0.0025 # (same)

# - Genetic Query Optimizer -

#geqo = true
#geqo_threshold = 12
#geqo_effort = 5 # range 1-10
#geqo_pool_size = 0 # selects default based on effort
#geqo_generations = 0 # selects default based on effort
#geqo_selection_bias = 2.0 # range 1.5-2.0

-------------------

TABLE의 문자열 필드는 모두 varchar(x)로 설정했습니다.
=========================================================

쿼리는

explain analyze
SELECT C.PRESS_TYPE, B.DYEG_NO, A.ASGN_NO, A.ASGN_SEQ, SHORT_NAME,

A.STYLE_CODE, D.CODE_NAME AS CLOTH_PART_NAME, F.CLOTH_NAME, G.COLOR_NAME,

A.BATH_TOTAL , A.BATH_CURR, A.BATH_STAT, A.SCHD_QTY, A.ASGN_QTY, A.ASGN_WGT,

C.TEST_NO, A.ASGN_NAME, A.SCHD_DATE, A.ODR_NO, A.ODR_SEQ, '' AS STAT
FROM SPBKAGO0 A
LEFT OUTER JOIN SPDDYEGA B ON A.ASGN_NO=B.ASGN_NO AND A.ASGN_SEQ=B.ASGN_SEQ
LEFT OUTER JOIN SPC_LINK C ON A.ODR_NO = C.ODR_NO AND A.ODR_SEQ = C.ODR_SEQ
JOIN SPACODE0 D ON A.CLOTH_PART= D.CODE AND D.CODE_TYPE = 'CLOTH_PART'
JOIN SPACUST0 E ON A.CUST_CODE = E.CUST_CODE
JOIN SPACLTH0 F ON A.CUST_CODE = F.CUST_CODE AND A.CLOTH_CODE = F.CLOTH_CODE
JOIN SPACLOR0 G ON A.CUST_CODE = G.CUST_CODE AND A.COLOR_CODE = G.COLOR_CODE
WHERE A.CUST_CODE LIKE '%'
AND C.TEST_NO IS NOT NULL
AND A.SCHD_DATE BETWEEN '2005-01-11' AND '2005-11-11'
AND B.ASGN_NO IS NULL ORDER BY A.ASGN_NO, A.ASGN_SEQ
이고요

--------------------------------------------------------------

pgAmin3의 SQL에서 실행하면

 

"Sort (cost=4185.58..4199.20 rows=5448 width=194) (actual time=750.000..750.000 rows=450 loops=1)"
" Sort Key: a.asgn_no, a.asgn_seq"
" -> Merge Join (cost=3551.31..3847.49 rows=5448 width=194) (actual time=641.000..750.000 rows=450 loops=1)"
" Merge Cond: ("outer".odr_no = "inner".odr_no)"
" Join Filter: ("inner".odr_seq = "outer".odr_seq)"
" -> Index Scan using spc_link_odr_no on spc_link c (cost=0.00..232.92 rows=5384 width=42) (actual time=0.000..46.000 rows=5384 loops=1)"
" Filter: (test_no IS NOT NULL)"
" -> Sort (cost=3551.31..3551.79 rows=191 width=171) (actual time=641.000..657.000 rows=11581 loops=1)"
" Sort Key: a.odr_no"
" -> Hash Join (cost=3016.31..3544.08 rows=191 width=171) (actual time=578.000..641.000 rows=858 loops=1)"
" Hash Cond: (("outer".cust_code = "inner".cust_code) AND ("outer".cloth_code = "inner".cloth_code))"
" -> Merge Join (cost=2961.39..3312.54 rows=3657 width=165) (actual time=562.000..625.000 rows=858 loops=1)"
" Merge Cond: (("outer".cust_code = "inner".cust_code) AND ("outer".color_code = "inner".color_code))"
" -> Index Scan using spaclor0_pkey on spaclor0 g (cost=0.00..267.61 rows=3833 width=32) (actual time=0.000..31.000 rows=3829 loops=1)"
" -> Sort (cost=2961.39..2970.78 rows=3756 width=149) (actual time=562.000..562.000 rows=858 loops=1)"
" Sort Key: a.cust_code, a.color_code"
" -> Hash Join (cost=2256.99..2738.38 rows=3756 width=149) (actual time=422.000..547.000 rows=858 loops=1)"
" Hash Cond: (("outer".cloth_part)::text = ("inner".code)::text)"
" -> Merge Left Join (cost=2250.35..2473.32 rows=9816 width=145) (actual time=422.000..532.000 rows=858 loops=1)"
" Merge Cond: (("outer".asgn_no = "inner".asgn_no) AND ("outer".asgn_seq = "inner".asgn_seq))"
" Filter: ("inner".asgn_no IS NULL)"
" -> Sort (cost=1400.64..1425.18 rows=9816 width=129) (actual time=312.000..312.000 rows=9817 loops=1)"
" Sort Key: a.asgn_no, a.asgn_seq"
" -> Seq Scan on spbkago0 a (cost=0.00..749.80 rows=9816 width=129) (actual time=0.000..155.000 rows=9817 loops=1)"
" Filter: ((cust_code ~~ '%'::text) AND ((schd_date)::text >= '2005-01-11'::text) AND ((schd_date)::text <= '2005-11-11'::text))"
" -> Sort (cost=849.71..872.11 rows=8959 width=35) (actual time=110.000..126.000 rows=8959 loops=1)"
" Sort Key: b.asgn_no, b.asgn_seq"
" -> Seq Scan on spddyega b (cost=0.00..261.59 rows=8959 width=35) (actual time=0.000..32.000 rows=8959 loops=1)"
" -> Hash (cost=6.61..6.61 rows=10 width=16) (actual time=0.000..0.000 rows=0 loops=1)"
" -> Seq Scan on spacode0 d (cost=0.00..6.61 rows=10 width=16) (actual time=0.000..0.000 rows=8 loops=1)"
" Filter: ((code_type)::text = 'CLOTH_PART'::text)"
" -> Hash (cost=49.71..49.71 rows=1040 width=54) (actual time=16.000..16.000 rows=0 loops=1)"
" -> Hash Join (cost=5.71..49.71 rows=1040 width=54) (actual time=0.000..16.000 rows=1040 loops=1)"
" Hash Cond: ("outer".cust_code = "inner".cust_code)"
" -> Seq Scan on spaclth0 f (cost=0.00..28.40 rows=1040 width=37) (actual time=0.000..0.000 rows=1040 loops=1)"
" -> Hash (cost=5.37..5.37 rows=137 width=17) (actual time=0.000..0.000 rows=0 loops=1)"
" -> Seq Scan on spacust0 e (cost=0.00..5.37 rows=137 width=17) (actual time=0.000..0.000 rows=137 loops=1)"
"Total runtime: 750.000 ms"

 

이렇게 나옵니다.

Planner Method Configuration 와 Planner Cost Constants의 random_page_cost = 3 가 #으로

막혀일을때는

"Total runtime: 813.000 ms"
이정도가 나옵니다.

근데 실제환경에서는 20~30초 정도 걸린다는데 빨리 쿼리하는 방법이 없을까요?

좀 질문이 심한거 같은데 좀 부탁드립니다.

 

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

postgresql.conf 파일에서,

주석으로 처리 되어있는 것은 default 값입니다.

즉, 그 값을 바꾸면, 주석을 풀어라는 뜻이거든요.

 

그건 그렇고,

explain의 cost 값들이 비교적 골고루 각 plan 에서 쓰고 있네요. :)

다시 말하면, 현재 쿼리로는 postgresql 쪽에서 돌리면, 그렇게 밖에 나오지 않는 것을 의미합니다.

 

방법을 찾는 방법은 각 plan 들을 하나씩 실행해보면서, 실재 쿼리 속도를 살펴보고, 그중 제일 많이 걸리는 놈을 찾고, 그것을 줄여나가는 방법 밖에 없을 것같습니다.

 

근데, 질문 하실 때는 읽는 사람도 좀 편하게 고려해주는 배려가 필요할 것같네요.

김상기(ioseph)님이 2005-11-11 21:59에 작성한 댓글입니다.

쿼리가 너무 복잡해서 어지럽네요.

 

table이 이렇게 많으니 각 table의 현황과 인덱스 여부를 알지 않고는 어려울 것 같고... 그것을 다 알려주신다고 해도 간단해 보이지 않아 충분히 검토하기 힘들 것 같네요. ^^

 

조인 하는 컬럼에는 인덱스를 걸어주시구요. vacuum analyze를 실행해 주세요. (아마 이미 이렇게 하셨을 듯...)

 

그리고 random_page_code를 좀 더 낮춰보세요. 인덱스를 타는 것이 무조건 빠른 것은 아니니까 실제 처리 시간을 보시면서 조금씩 조절해 보세요. 2 이하로는 내리만 말라고 하더군요. 0.1이나 0.2 정도씩 낮춰보세요.

 

그리고 실제 DB에서의 query plan이 지금 보여주신 것과 같은지도 확인해 보시는 것이 좋겠네요.

 

DB 설계를 개선할 여지가 없고 쿼리도 최적화 되었다면 서버의 하드웨어를 향상시킬 수 밖에 없겠죠. 하드 8개 이상으로 구성된 RAID와 4Way CPU.. 8G 메모리... ㅎㅎ

박성철(gyumee)님이 2005-11-12 14:09에 작성한 댓글입니다.

요즘 회사서 쿼리튜닝을 몇 개 했습니다

실행속도를 수백~수천배 단축하니까 성취감이;;

여튼 같은 효과를 내는 쿼리를 여러개 만들어 보세요..

그런데 쿼리가 약간 다르거나 많이 달라도 쿼리 플랜은 같을 수도 있습니다. 더 안좋은 성능이 나올 수도 있구요

저같은 경우는 어떤 쿼리를 함수를 만들어서 풀었습니다. 배열 컬럼과 =any() 로 조인을 했어야 했는데 함수를 만들어서 배열을 문자열로 만든 후 in () 으로 해서 인덱스를 타게 했더니 20초 정도 걸리던 쿼리가 50ms 이하로 떨어졌습니다..

상황에 따라 많이 달라지겠지만요 최적의 쿼리를 만들기 위해서 이것저것 해보다 보면 어떤 쿼리도 최적화 할 수 있겠구나.. 라는 생각이 들더라구요..

신기배(소타)님이 2005-11-12 14:41에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
64208.1 에서 add_missing_from?? [3]
장효순
2005-11-15
6565
6418pgsql.so 파일에 관하여.. [1]
한종희
2005-11-14
3084
6417댓글로 쓰기에 양이 많아서 다시 올립니다 [1]
김이수
2005-11-13
2576
6414어찌하면 빨라질까요? 인덱스를 안쓰는거 같은데... [3]
김이수
2005-11-11
4070
6413SQL_ASCII 의 DB 를 UNICODE 로 변경하려면. [1]
가우나라
2005-11-11
2441
6412Group by 질문이여... [1]
조성배
2005-11-11
2080
6411vacuum 에 관해서 질문드립니다. [3]
가우나라
2005-11-11
2989
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.017초, 이곳 서비스는
	PostgreSQL v16.4로 자료를 관리합니다