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 9313 게시물 읽기
No. 9313
order by 와 limit을 같이 쓸 경우..
작성자
postgresking
작성일
2013-07-08 19:46ⓒ
2013-07-09 16:09ⓜ
조회수
10,285

안녕하세요

postgres에서 limit과 order by를 함께 사용할 경우 explain 변화하는 것에 대하여 궁금해서 글을 올립니다.

order by만 사용할 경우

Sort  (cost=402354.82..402487.52 rows=53083 width=202) (actual time=2979.700..2979.879 rows=289 loops=1)
  Sort Key: af.ctime
  Sort Method: quicksort  Memory: 98kB
  ->  Merge Join  (cost=357400.19..398188.87 rows=53083 width=202) (actual time=2579.980..2978.984 rows=289 loops=1)
        Merge Cond: (af.f_seq = testdb.p_seq)
        ->  Nested Loop  (cost=0.00..77544.95 rows=32400 width=66) (actual time=0.045..368.099 rows=30731 loops=1)
              ->  Index Scan using test2_f_seq on test2 af  (cost=0.00..13156.55 rows=32400 width=45) (actual time=0.018..43.278 rows=30770 loops=1)
              ->  Index Scan using test_pk on test mf  (cost=0.00..1.98 rows=1 width=21) (actual time=0.006..0.007 rows=1 loops=30770)
                    Index Cond: (f_seq = af.f_seq)
        ->  Sort  (cost=357400.19..357532.89 rows=53083 width=152) (actual time=2579.415..2579.716 rows=423 loops=1)
              Sort Key: testdb.p_seq
              Sort Method: quicksort  Memory: 78kB
              ->  Hash Left Join  (cost=306023.52..353234.24 rows=53083 width=152) (actual time=2349.350..2578.389 rows=423 loops=1)

이와 같이 merge 로 잘풀립니다.

그러나

order by 뒤에 limit을 추가하면

Limit  (cost=306027.65..306517.42 rows=1 width=202) (actual time=3303.627..3303.628 rows=1 loops=1)
  ->  Nested Loop  (cost=306027.65..26304090.97 rows=53083 width=202) (actual time=3303.624..3303.624 rows=1 loops=1)
        Join Filter: (af.f_seq = testdb.p_seq)
        Rows Removed by Join Filter: 523254
        ->  Nested Loop  (cost=0.00..150922.10 rows=32400 width=66) (actual time=0.031..16.372 rows=1238 loops=1)
              ->  Index Scan using test2_ctime on test2 af  (cost=0.00..31217.30 rows=32400 width=45) (actual time=0.016..1.928 rows=1238 loops=1)
              ->  Index Scan using test_pk on test mf  (cost=0.00..3.68 rows=1 width=21) (actual time=0.007..0.008 rows=1 loops=1238)
                    Index Cond: (f_seq = af.f_seq)
        ->  Materialize  (cost=306027.65..353503.79 rows=53083 width=152) (actual time=1.912..2.332 rows=423 loops=1238)
              ->  Hash Left Join  (cost=306027.65..353238.37 rows=53083 width=152) (actual time=2366.365..2596.600 rows=423 loops=1)
                    Hash Cond: (testdb.p_seq = mf2.f_seq)
                    ->  Hash Left Join  (cost=229522.95..266379.71 rows=53083 width=118) (actual time=1838.027..2025.391 rows=423 loops=1)

이와 같이 nested loop로 변화하면서 속도가 느려집니다.

order by 뒤에 limit을 하면 sort된 것을 limit으로 짜르는 구조가 아닌건가지 알고 싶고

이와 비슷한 경험이 있으시다면 해결방법이 있다면 알려주시면 감사하겠습니다.

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

실행계획이 이상합니다.

order by ... limit

라면, 일단 그 실행계획에 order by 작업을 위한 sort 작업이 있어야하는데, 그게 안보이네요.

 

두 쿼리의 차이가 정말

...... order by af.ctime

...... order by af.ctime limit 1

이것 빼고는 차이가 없는지부터 확인을 해봐야할 것 같습니다.

 

김상기(ioseph)님이 2013-07-09 11:04에 작성한 댓글입니다.

order by 절의 컬럼리스트와 인덱스 컬럼리스트가 동일하면 정렬되서 저장되는 b-tree인덱스 특성을 이용해 인덱스스캔으로 sort작업을 대체할수 있습니다.
가능하다고 해서 항상 이런 방식으로 풀리는건 아니고 옵티마이저의 취사선택인데요.
limit 가 추가되면 보다 적은 양의 인덱스 스캔으로 처리할 가능성이 높이지기 때문에 sort보다는 인덱스 스캔을 선택할 확률이 높아지는겁니다.

이 경우에는 set statistics 설정으로 해당 컬럼의 통계정보 양을 늘려주거나 set enable_nestloop to false 설정으로 실행계획을 고정해서 원하는 방식으로 유도할수 있습니다.
 

 

 

백수환(back17)님이 2013-07-16 20:56에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
9316디비 인코딩 관련 웹 페이지(PHP) 한글 출력문제 [4]
souler
2013-07-14
9954
9315복원 시 문제점 [1]
초보
2013-07-13
9708
9314bytea 에 담겨진 이미지 가져오는게 안되네요 [1]
김선환
2013-07-09
10032
9313order by 와 limit을 같이 쓸 경우.. [2]
postgresking
2013-07-08
10285
9312인덱스 리빌드 관련 문의 [3]
초보자
2013-07-08
10016
9311갑자기 오전에 createdb를 하면 생성이 안됩니다. [3]
강승준
2013-07-08
9999
9310PostgreSQL에서 fuction간 호출문제 [1]
최종호
2013-07-05
9644
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.019초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다