이름별로 모든 열을 다른 열 순서로 선택하는 것보다 SELECT *가 더 빠른 이유는 무엇입니까?


12

열 a, b, c, d, e, f, g, h, i, j, k가있는 테이블에서 다음을 얻습니다.

select * from misty order by a limit 25;
Time: 302.068 ms

과:

select c,b,j,k,a,d,i,g,f,e,h from misty order by a limit 25;
Time: 1258.451 ms

열을 기준으로 빠르게 선택할 수있는 방법이 있습니까?

최신 정보:

테이블에 인덱스가없고 새로 생성 된 인덱스

EXPLAIN ANALYZE는 다음과 같습니다.

explain analyze select * from misty order by a limit 25;

Limit  (cost=43994.40..43994.46 rows=25 width=190) (actual time=404.958..404.971 rows=25 loops=1)
->  Sort  (cost=43994.40..45731.11 rows=694686 width=190) (actual time=404.957..404.963 rows=25 loops=1)
     Sort Key: a
     Sort Method: top-N heapsort  Memory: 28kB
     ->  Seq Scan on misty  (cost=0.00..24390.86 rows=694686 width=190) (actual time=0.013..170.945 rows=694686 loops=1)
Total runtime: 405.019 ms
(6 rows)

과:

explain analyze select c,b,j,k,a,d,i,g,f,e,h from misty order by a limit 25;

Limit  (cost=43994.40..43994.46 rows=25 width=190) (actual time=1371.735..1371.745 rows=25 loops=1)
->  Sort  (cost=43994.40..45731.11 rows=694686 width=190) (actual time=1371.733..1371.736 rows=25 loops=1)
     Sort Key: a
     Sort Method: top-N heapsort  Memory: 28kB
     ->  Seq Scan on misty  (cost=0.00..24390.86 rows=694686 width=190) (actual time=0.015..516.355 rows=694686 loops=1)
Total runtime: 1371.797 ms
(6 rows)

열이 색인되어 있습니까? 설명 분석을 게시 할 수 있습니까?
user_0

1
연속해서 두 번 선택하고 시간을 비교해야합니다. 두 번째 쿼리의 캐시에있는 데이터는 시간의 차이를 설명 할 수 있습니다.
Walter Mitty

1
나는 발음이 다르지만 차이점을보고 있습니다. 내 테이블의 행 = 514431 너비 = 215가 있으며 select *사례 의 경우 약 1.5 초 , 다른 순서로 나열된 열이있는 선택 의 경우 약 2.2 초가 나타납니다 .
Colin 't Hart

테이블에 정의 된 것과 동일한 순서로 모든 열을 나열하면 거의 같은 시간이 I와 같습니다 select *.
Colin 't Hart

2
제목이 잘못되었습니다. 문제는 실제로 정렬 기간이 출력 열의 순서에 따라 달라지는 이유입니다.
Daniel Vérité

답변:


12

이것은 pgsql-hackers 메일 링리스트에 게시 되었으며 간단히 대답 하려고 했습니다. 대상 목록 (지정된 열)이 관계의 튜플 설명자 (열 수와 순서 모두)와 정확히 일치하는 경우 기본 스캔은 둘러싸는 정렬 노드에서 직접 사용할 수있는 튜플을 반환 할 수 있습니다. 반면, 대상 목록이 (지정된 열 수 또는 순서대로) 일치하지 않으면 스캔은 추가 작업을 수행하기 위해 Sort의 데이터 준비 단계가 필요한 튜플 형식을 반환합니다 (내부 튜플 형식에서 정렬 코드에서 직접 사용할 수있는 형식).

그런데 '*'는 내부적으로 관계의 튜플 설명자와 (직관적으로) 일치하는 목록으로 변환됩니다.

편집 : 후자의 EXPLAIN ANALYZE의 Seq Scan의 실제 시간을 살펴보면 이전보다 더 많은 시간을 볼 수 있습니다. 스캔이 추가 프로젝션 단계 (즉, 힙 튜플을 내부 값 [], nulls [] 형식으로 변환)를 수행했기 때문에 발생했습니다. 그리고 이것이 일어나기 때문에 상위 정렬 노드는 데이터 초기화에서 추가 작업을 수행해야했습니다. 실제 정렬 단계가 이해하는 튜플 형식으로 다시 변환해야했습니다. 그것은 Sort의 시작 비용에서 분명합니다. 전자의 경우에는 발생하지 않습니다. 즉, 두 스캔 모두 튜플을 그대로 반환하고 정렬의 초기화 단계에서 튜플을 복사합니다.


@ Colin'tHart, 그것이 의미가 있기를 바랍니다.
amitlan

예. "포인터 셔플 링"을 사용하여 해당 단계를 건너 뛰거나 더 짧게 만들 수 있기를 바랐지만 pgsql-hackers에 대한 토론입니다.
Colin 't Hart

최근 논리 열 순서 지정 작업이 부활 함에 따라 일부 개선 사항이있을 수 있습니다 .
amitlan

나는 이미 그것에 대해 생각하고 있었으면 좋겠다!
Colin 't Hart

친애하는 각하, 일부 대신 열만 필요한 경우 어느 것이 더 빠를까요? * 또는 some_of_columns를 선택 하시겠습니까? 고마워
sgon00
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.