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
連続して2つの選択を行い、時間を比較することに注意する必要があります。2番目のクエリのキャッシュ内のデータは、時間の違いを説明できます。
ウォルターミッティ

1
それほど顕著ではありませんが、違いも見られます。私のテーブルにはrows = 514431 width = 215があり、異なる順序select *で列がリストされている selectでは約1.5秒、selectでは約2.2秒になります。
コリン 'ハート

テーブルで定義されているのと同じ順序ですべての列をリストすると、Iとほぼ同じ時間になりselect *ます。
コリン 'ハート

2
タイトルは誤解を招くです。問題は、ソートの期間が出力列の順序に依存する理由です。
ダニエルヴェリテ

回答:


12

これはpgsql-hackersメーリングリストに投稿され、私は試しましたそこで簡単に答えよしました。ターゲットリスト(指定された列)がリレーションのタプル記述子と正確に一致する場合、つまり、列数と順序の両方で一致する場合、基礎となるスキャンは、囲むSortノードによって直接消費可能なタプルを返すことができます。一方、ターゲットリストが(順序または指定された列の数で)一致しない場合、スキャンは、追加の作業を実行するためにSortのデータ準備ステップを必要とするタプルのフォームを返します(内部タプル形式から並べ替えコードで直接使用できる形式)。

ところで、「*」はリレーションのタプル記述子に(直感的に)一致するリストに内部的に変換されます。

編集:後者のEXPLAIN ANALYZEのSeq Scanの実際の時間を見ると、前者の時間よりも多いことがわかります。これは、スキャンが追加の投影ステップ(つまり、ヒープタプルを内部値[]、nulls []形式に変換する)を実行したために発生しました。そしてそれが起こったので、上部のソートノードはそのデータ初期化、つまり実際のソートステップが理解できるタプル形式に変換するという追加の作業を行わなければなりませんでした。これは、Sortの起動コストから明らかです。前者の場合、それは起こりません。つまり、スキャンはタプルをそのまま返し、ソートの初期化ステップは単にタプルをコピーします。


@ Colin'tHart、それが理にかなっていることを願っています。
アミトラン

はい。「ポインターシャッフル」を使用して、そのステップをスキップしたり短くしたりできるといいのですが、それはpgsql-hackersの議論です。
コリン 'ハート

論理列の順序付け作業の最近の復活により、地平線にいくつかの改善があるかもしれません。
アミトラン

私はすでにそれについて考えていて、そう願っていました!
コリン 'ハート

親愛なる、すべてではなくいくつかの列だけが必要な場合、どちらが速くなりますか?select *またはsome_of_columns?どうもありがとう。
sgon00
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.