Saya punya tabel PostgreSQL. select *
sangat lambat sedangkan select id
bagus dan cepat. Saya pikir mungkin ukuran barisnya sangat besar dan butuh beberapa saat untuk transportasi, atau mungkin ada beberapa faktor lain.
Saya membutuhkan semua bidang (atau hampir semuanya), jadi memilih hanya sebagian bukan perbaikan cepat. Memilih bidang yang saya inginkan masih lambat.
Berikut skema tabel saya minus namanya:
integer | not null default nextval('core_page_id_seq'::regclass)
character varying(255) | not null
character varying(64) | not null
text | default '{}'::text
character varying(255) |
integer | not null default 0
text | default '{}'::text
text |
timestamp with time zone |
integer |
timestamp with time zone |
integer |
Ukuran kolom teks bisa berapa saja. Tapi tetap saja, tidak lebih dari beberapa kilobyte dalam kasus terburuk.
Pertanyaan
- Apakah ada sesuatu tentang ini yang berteriak 'tidak efisien gila'?
- Apakah ada cara untuk mengukur ukuran halaman di baris perintah Postgres untuk membantu saya men-debug ini?
length(*)
bukan hanyalength(field)
? Saya tahu itu bukan byte byte tetapi saya hanya perlu nilai sekitar.Jawaban:
Q2:
way to measure page size
PostgreSQL menyediakan sejumlah Fungsi Ukuran Objek Basis Data . Saya mengemas yang paling menarik dalam kueri ini dan menambahkan beberapa Fungsi Akses Statistik di bagian bawah. (Modul pgstattuple tambahan menyediakan fungsi yang lebih bermanfaat.)
Ini akan menunjukkan bahwa metode yang berbeda untuk mengukur "ukuran baris" mengarah ke hasil yang sangat berbeda. Itu semua tergantung pada apa yang ingin Anda ukur, tepatnya.
Permintaan ini membutuhkan Postgres 9.3 atau lebih baru . Untuk versi yang lebih lama lihat di bawah.
Menggunakan
VALUES
ekspresi dalamLATERAL
subquery , untuk menghindari mengeja perhitungan untuk setiap baris.Ganti
public.tbl
(dua kali) dengan nama tabel yang memenuhi syarat untuk skema Anda untuk mendapatkan tampilan yang kompak dari statistik yang dikumpulkan tentang ukuran baris Anda. Anda bisa membungkus ini menjadi fungsi plpgsql untuk penggunaan berulang, masukkan nama tabel sebagai parameter dan gunakanEXECUTE
...Hasil:
Untuk versi yang lebih lama (Postgres 9.2 atau lebih lama):
Hasil yang sama
Q1:
anything inefficient?
Anda dapat mengoptimalkan pesanan kolom untuk menghemat beberapa byte per baris, yang saat ini terbuang untuk pelurusan pelurusan:
Ini menghemat antara 8 dan 18 byte per baris. Saya menyebutnya "kolom tetris" . Detail:
Juga pertimbangkan:
sumber
, unnest(val) / ct
dengan, (LEAST(unnest(val), unnest(val) * ct)) / (ct - 1 + sign(ct))
dan tidak akan membuang. Dasar pemikirannya adalah bahwa, kapanct
pun0
,val
akan digantikan oleh0
danct
akan digantikan oleh1
.Perkiraan ukuran baris, termasuk konten ed TOAST , mudah didapat dengan menanyakan panjang representasi TEXT dari seluruh baris:
Ini adalah perkiraan dekat dengan jumlah byte yang akan diambil sisi klien saat menjalankan:
... dengan asumsi bahwa pemanggil permintaan meminta hasil dalam format teks, yang merupakan apa yang dilakukan sebagian besar program (format biner dimungkinkan, tetapi itu tidak sebanding dengan masalah dalam kebanyakan kasus).
Teknik yang sama dapat diterapkan untuk menemukan baris
N
"terbesar dalam teks" daritablename
:sumber
Ada beberapa hal yang bisa terjadi. Secara umum, saya ragu bahwa panjang adalah masalah proksimal. Saya menduga Anda memiliki masalah terkait panjang.
Anda mengatakan bidang teks bisa mencapai beberapa k. Baris tidak dapat melebihi 8k dalam penyimpanan utama, dan kemungkinan bidang teks Anda yang lebih besar telah dipanggang , atau dipindahkan dari penyimpanan utama ke penyimpanan yang diperluas dalam file yang terpisah. Ini membuat penyimpanan utama Anda lebih cepat (jadi pilih id sebenarnya lebih cepat karena lebih sedikit halaman disk untuk diakses) tetapi pilih * menjadi lebih lambat karena ada I / O yang lebih acak.
Jika total ukuran baris Anda masih di bawah 8k, Anda dapat mencoba mengubah pengaturan penyimpanan. Namun, saya akan memperingatkan bahwa Anda bisa mendapatkan hal-hal buruk terjadi ketika memasukkan atribut besar ke penyimpanan utama, jadi sebaiknya jangan sentuh ini jika Anda tidak perlu dan jika Anda melakukannya, tetapkan batas yang tepat melalui kendala pemeriksaan. Jadi transportasi sepertinya bukan satu-satunya. Mungkin menyusun banyak, banyak bidang yang memerlukan pembacaan acak. Sejumlah besar pembacaan acak juga dapat menyebabkan cache meleset, dan sejumlah besar memori yang dibutuhkan dapat mengharuskan hal-hal terwujud pada disk dan sejumlah besar baris lebar, jika bergabung ada (dan ada satu jika TOAST terlibat) mungkin memerlukan lebih mahal bergabung dengan pola, dll.
Hal pertama yang akan saya lakukan adalah memilih lebih sedikit baris dan melihat apakah itu membantu. Jika itu berhasil, Anda dapat mencoba menambahkan lebih banyak RAM ke server juga, tetapi saya akan mulai dan melihat di mana kinerja mulai jatuh karena perubahan rencana dan cache gagal terlebih dahulu.
sumber
Menggunakan Fungsi Ukuran Objek Basis Data yang disebutkan di atas:
sumber