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 6854 게시물 읽기
No. 6854
실행계획 한번 봐주세요.
작성자
백수환(back17)
작성일
2006-10-13 11:51ⓒ
2006-10-13 11:53ⓜ
조회수
4,306

test테이블에 name,point 컬럼이 있습니다.


아래는 name별 point 기준으로 상위3개씩만 뽑아오는 쿼리와 실행계획입니다.


쿼리는 셀프조인형태로 서브쿼리의 값과 외부쿼리의 값을 비교하는데요


실행계획을 보시면 서브쿼리에서 먼저 인덱스 스켄을 한 후  외부 쿼리에서는 subplan의 결과값으로

Filter처리를 하고 있습니다.


제 예상은 외부나 내부 어느 한쪽의 테이블을 읽으면서 nested loop조인 형식으로 하나씩 값을 반대쪽이 쿼리에 공급하는 플랜이였습니다.


글을쓰다보니 제가 바보 같은 생각을 했네요..;;;

인라인뷰와 같이 집합을 만들어 놓지 않는 이상 nested loop로 풀리지 않는게 맞는거 같네요.


근데 어떻게 아래과 같은 실행계획이 나온지는 잘모르겠습니다.

어느쪽이 됐든 한쪽의 값을 다른쪽의 쿼리에 공급해줘야 할꺼 같은데 이 실행계획을 봐선 이해가 안되네요.


선배님들 조언부탁드립니다.


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


select t1.name, t1.point

from test t1

where t1.point >= (select min(t3.point)

                         from (select point

                                  from test t2

                                 where t2.name = t1.name

                                 order by t2.point desc limit 3) t3)

order by name, point desc


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


Sort  (cost=16577.61..16602.62 rows=10004 width=14)

  Sort Key: name, point

  ->  Seq Scan on test t1  (cost=0.00..15912.93 rows=10004 width=14)

        Filter: (point > (subplan))

        SubPlan

          ->  Aggregate  (cost=0.50..0.51 rows=1 width=4)

                ->  Limit  (cost=0.00..0.45 rows=4 width=4)

                      ->  Index Scan Backward using test_point on test t2  (cost=0.00..1123.75 rows=10004 width=4)

                            Filter: ((name)::text = ($0)::text)

이 글에 대한 댓글이 총 4건 있습니다.
nonun=# EXPLAIN ANALYZE select t1.name, t1.point from test t1 where t1.point >= (select t2.point from test t2 where t2.name = t1.name order by t2.point desc limit 1 offset 2) order by name, point desc;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=100000019.96..100000019.97 rows=3 width=9) (actual time=0.212..0.212 rows=6 loops=1)
Sort Key: name, point
-> Seq Scan on test t1 (cost=100000000.00..100000019.94 rows=3 width=9) (actual time=0.091..0.148 rows=6 loops=1)
Filter: (point >= (subplan))
SubPlan
-> Limit (cost=1.25..1.88 rows=1 width=4) (actual time=0.012..0.012 rows=1 loops=10)
-> Index Scan Backward using idx_test01 on test t2 (cost=0.00..3.13 rows=5 width=4) (actual time=0.009..0.011 rows=3 loops=10)
Filter: (name = $0)
Total runtime: 0.287 ms
(9 rows)

이렇게 쿼리를 약간 단순화 할 수는 있습니다. 결과는 같고요. 이 플랜은 enable_seqscan=false로 seqscan을 강제로 끈 상태입니다. 데이터 갯수가 제쪽이 훨씬 적어서 플랜이 다를 수 있습니다. 코스트가 어디에서 확 증가하는지 확인만 하시면 됩니다~

어쨌든 이런식으로 처리가 안되면 함수를 만들어서 해보셔도 좋을것 같습니다. name, point에 멀티컬럼 인덱스를 거시고 distinct name 으로 쿼리를 주고 그 name의 결과를 함수에 넘기면 3개씩 찾아오는 방식으로요. 오히려 이 방식이 내부적으로 쿼리가 수백번 증가하지만 짧은 쿼리의 조합이므로 1분씩 걸리던 쿼리가 2~3초에 끝날 수 있습니다.

그리고 위 쿼리의 경우 "A"라는 값이 name에 있고 point에 5, 4, 3, 3, 3, 2, 1 처럼 값이 있을 때 3개가 아니라 5개가 리턴됩니다. 쿼리가 point >= 3 이니까 5, 4, 3, 3, 3 이 리턴됩니다.

수고하세요~
신기배(소타)님이 2006-10-13 14:31에 작성한 댓글입니다.
이 댓글은 2006-10-13 14:34에 마지막으로 수정되었습니다.

백수환님의 경우에는 정렬을 하는 시점에서 예상 코스트가 확 증가합니다.

EXPLAIN 시 ANALYZE 를 붙여주셔서 실제의 코스트도 확인을 해보세효~


맨 마지막의 order by name, point desc 를 빼보시고 원하는 속도가 나오시면 빠른 디스크의 테이블 스페이스에 create temp table as 로 테이블로 만든 후 정렬해보시는 것도 도움이 될 수 있습니다

신기배(소타)님이 2006-10-13 14:37에 작성한 댓글입니다.
이 댓글은 2006-10-13 14:39에 마지막으로 수정되었습니다.

답변감사드립니다.

그러고보니 틀린 쿼리군요..ㅜㅡ;

답변을 보다 궁금한점이 생겼는데요 ^^;;

플랜의 cost를 보면 
cost=16577.61..16602.62 
이렇게 나오는데 중간에 ..을 기준으로 왼쪽과 오른쪽의 차이는 무엇인가요?

그리고 실제 쿼리를 수행하면 플랜의 total runtime의 값보다는 빠르게 수행됩니다.
제 질문의 쿼리로 테스트해보니 아래와 같이 차이가 나는데요.. 왜그런거죠?

실제수행시간 : 1172
플랜의 total runtime : 4032 

postgresql을 첨 접하는 거라 모든게 새롭습니다 ;;;
좋은 하루 되세요~^_^

백수환(back17)님이 2006-10-13 15:22에 작성한 댓글입니다.
이 댓글은 2006-10-13 15:25에 마지막으로 수정되었습니다.

수행시간이 여러가지 관점이 있습니다.

실제 수행 시간, 수행되서 클라이언트까지 전달되는 시간

psql에서 \timing 해보시면 후자의 시간까지 보실 수 있습니다.


(cost=?..? rows=? width=?) 를 보는 방법은

http://www.physiol.ox.ac.uk/Computing/Online_Documentation/postgresql/performance-tips.html#USING-EXPLAIN

에 잘 나와 있습니다~


cost 는 옵티마이저가 판단하는 수치이고 explain analyze 시 actual time은 실제로 걸린 시간입니다. 이 격차가 적으면 적을수록 옵티마이저의 예상이 적중하는 것이구요.

신기배(소타)님이 2006-10-13 15:34에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
6862db 필드명을 like 조건문으로 주려고 합니다. [1]
김태우
2006-10-17
3426
6861select 문에서 데이타베이스간 참조는 (cross_database reference)어떻게 하는지..예제 부탁드립니다. [1]
김승일
2006-10-17
3494
6857sql 포함관계에대한 함수? 혹은 비슷한것 에대해 알려주세요 [1]
초보
2006-10-13
3387
6854실행계획 한번 봐주세요. [4]
백수환
2006-10-13
4306
6853같은 테이블명이 2개씩 존재합니다..
star1533
2006-10-12
3333
6852이거 가능한가여.. [2]
조진우
2006-10-11
3589
6851postgresql 데이타베이스에관한
초보
2006-10-11
4235
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.025초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다