Mengapa SELECT * jauh lebih cepat daripada memilih semua kolom (dalam urutan kolom yang berbeda) dengan nama?

12

Di atas meja dengan kolom a, b, c, d, e, f, g, h, i, j, k saya mendapatkan:

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

Dan:

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

Apakah ada cara untuk membuat kolom pilih dengan cepat?

Memperbarui:

Tidak ada indeks di atas meja, yang baru dibuat

Berikut adalah EXPLAIN ANALYZE, sepertinya tidak terlalu membantu:

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)

Dan:

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)
Evgeny
sumber
Apakah kolom a diindeks? Bisakah Anda memposting menjelaskan analisis?
user_0
1
Anda harus berhati-hati dalam membuat dua pilihan berturut-turut dan membandingkan waktu. Data dalam cache pada kueri kedua dapat menjelaskan perbedaan waktu.
Walter Mitty
1
Saya melihat perbedaan juga, meskipun tidak diucapkan. Meja saya memiliki baris = 514431 lebar = 215, dan saya mendapatkan kira- select *kira 1,5s untuk kasing dan kira-kira 2,2s untuk seleksi dengan kolom yang tercantum dalam urutan yang berbeda .
Colin 't Hart
Jika saya mencantumkan semua kolom dalam urutan yang sama seperti yang didefinisikan dalam tabel, saya mendapatkan kira-kira waktu yang sama seperti jika saya select *.
Colin 't Hart
2
Judul itu menyesatkan. Pertanyaan sebenarnya adalah mengapa durasi pengurutan tergantung pada urutan kolom output.
Daniel Vérité

Jawaban:

12

Ini diposting ke milis pgsql-hacker dan saya mencoba menjawab secara singkat di sana. Tampaknya jika daftar target (kolom yang ditentukan) cocok dengan deskriptor tuple relasi, yaitu, baik dalam jumlah kolom dan urutan, maka pemindaian yang mendasarinya dapat mengembalikan tupel yang langsung dikonsumsi oleh node Urut yang terlampir. Di sisi lain, jika daftar target tidak cocok (baik dalam urutan atau jumlah kolom yang ditentukan), pemindaian mengembalikan bentuk tupel yang memerlukan langkah persiapan data Sortir untuk melakukan pekerjaan tambahan (mengkonversi dari format tuple internal ke format langsung dikonsumsi oleh kode penyortiran).

Omong-omong, '*' diubah secara internal menjadi daftar yang (secara intuitif) cocok dengan deskriptor tuple relasi.

EDIT: Jika Anda melihat waktu aktual Seq Scan EXPLAIN ANALYZE Anda yang terakhir, Anda dapat melihatnya lebih dari sekadar former. Itu terjadi karena pemindaian melakukan langkah proyeksi tambahan (yaitu, mengubah tumpukan tumpukan menjadi nilai internal [], format nulls []). Dan karena itu terjadi, simpul Sortir atas harus melakukan pekerjaan ekstra dalam inisialisasi datanya, yaitu mengubahnya kembali ke format tuple yang dipahami oleh langkah sortasi. Itu terbukti dari biaya awal penyortiran. Itu tidak terjadi dalam kasus sebelumnya. Artinya, kedua pemindaian mengembalikan tuple sebagaimana adanya dan langkah inisialisasi sort hanya menyalinnya.

amitlan
sumber
@ Colin'tHart, harapan itu masuk akal.
amitlan
Iya. Saya akan berharap mungkin untuk melewati langkah itu atau membuatnya lebih pendek dengan menggunakan beberapa "pointer shuffling", tapi itu diskusi untuk peretas pgsql.
Colin 't Hart
Mungkin ada beberapa perbaikan di cakrawala dengan kebangkitan baru - baru ini pekerjaan pemesanan kolom logis.
amitlan
Saya sudah memikirkan hal itu dan berharap begitu!
Colin 't Hart
Tuan, jika saya hanya membutuhkan beberapa kolom saja, mana yang lebih cepat? pilih * atau pilih some_of_columns? Terima kasih banyak.
sgon00