Apakah pencarian indeks akan terasa lebih cepat dengan char vs varchar ketika semua nilai adalah 36 karakter

30

Saya memiliki skema lama (penafian!) Yang menggunakan id yang dihasilkan berbasis hash untuk kunci utama untuk semua tabel (ada banyak). Contoh dari id tersebut adalah:

922475bb-ad93-43ee-9487-d2671b886479

Tidak ada harapan untuk mengubah pendekatan ini, namun kinerja dengan akses indeks buruk. Mengesampingkan segudang alasan ini mungkin, ada satu hal yang saya perhatikan yang tampaknya kurang optimal - meskipun semua nilai id dalam semua tabel panjangnya persis 36 karakter, jenis kolomnya varchar(36), tidak char(36) .

Akankah mengubah jenis kolom menjadi panjang tetap char(36)menawarkan manfaat kinerja indeks yang signifikan , di luar peningkatan yang sangat kecil dalam jumlah entri per halaman indeks dll?

Yaitu apakah postgres berkinerja lebih cepat ketika berhadapan dengan tipe dengan panjang tetap daripada dengan tipe dengan panjang variabel?

Tolong jangan menyebutkan penghematan penyimpanan sangat kecil - itu tidak akan menjadi masalah dibandingkan dengan operasi yang diperlukan untuk membuat perubahan ke kolom.

Bohemian
sumber

Jawaban:

40

Tidak. Tidak ada keuntungan sama sekali . Manual ini secara eksplisit menyatakan :

Tip: Tidak ada perbedaan kinerja di antara ketiga jenis ini , selain dari ruang penyimpanan yang meningkat saat menggunakan jenis yang empuk, dan beberapa siklus CPU tambahan untuk memeriksa panjang saat menyimpan ke dalam kolom yang dibatasi panjang. Meskipun character(n)memiliki keunggulan kinerja di beberapa sistem basis data lain, tidak ada keunggulan seperti itu di PostgreSQL; sebenarnya character(n)biasanya yang paling lambat dari ketiganya karena biaya penyimpanan tambahan. Dalam sebagian besar situasi text atau character varyingharus digunakan sebagai gantinya .

Penekanan berani saya.

char(n)adalah tipe yang sebagian besar sudah ketinggalan zaman, tidak berguna. Tetap dengan varchar(n). Jika Anda tidak perlu memaksakan panjangnya, varcharatau textakan menjadi sedikit lebih cepat. Anda tidak akan dapat mengukur perbedaan.

Juga, jika semua string memiliki panjang 36 karakter, tidak ada penyimpanan yang disimpan, bahkan tidak ada yang sangat kecil. Keduanya memiliki ukuran yang persis sama pada disk dan RAM. Anda dapat menguji dengan pg_column_size()(pada ekspresi dan kolom tabel).

Terkait:

Anda tidak meminta opsi lain , tetapi saya akan menyebutkan dua:

  1. COLLATION- kecuali Anda menjalankan DB dengan pemeriksaan "C" . Kolasi sering diabaikan dan mungkin mahal. Karena string Anda tampaknya tidak bermakna dalam bahasa alami, mungkin tidak ada gunanya mengikuti COLLATIONaturan. Terkait:

    Perbandingan luas yang membandingkan (antara lain) pengaruh COLLATE "C"pada kinerja:

  2. UUID , jelas. String Anda secara mencurigakan terlihat seperti UUID (32 digit hex plus 4 pembatas). Akan jauh lebih efisien untuk menyimpan ini sebagaiuuidtipe dataaktual, yang lebih cepat dalam berbagai cara dan hanya menempati 16 byte - dibandingkan dengan 37 byte dalam RAM untuk salah satuchar(36)atauvarchar(36)(disimpan tanpa pembatas, hanya 32 karakter yang mendefinisikan), atau 33 byte pada disk. Tetapi padding alignment akan menghasilkan 40 byte dalam banyak kasus.)COLLATIONAkan tidak relevan untukuuidtipe data juga.

    SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid

    Ini mungkin membantu (bab terakhir):

    Lihat juga:

Erwin Brandstetter
sumber
apakah ini berarti bahwa char / varchar (n) yang panjangnya dibatasi akan menghabiskan siklus CPU dalam memeriksa kendala sementara bidang teks panjang variabel akan menyimpan teks secara terpisah dalam cara yang lebih mudah diakses dibandingkan dengan char, yang menang dalam skenario ini dan apakah ini menang bahkan layak dipertimbangkan untuk mengatakan 10 juta baris dengan selembar teks
PirateApp
1
@ PirateApp: char(n)hampir tidak pernah menang dalam hal apa pun. Jangan gunakan itu. Tipe data textdan varchar(tanpa pengubah panjang) adalah biner yang kompatibel dan berbagi karakteristik kinerja yang sama. Ada alasan historis bagi keduanya untuk hidup berdampingan di Postgres. Secara internal, textadalah tipe "disukai" di antara tipe string (yang dapat memengaruhi resolusi tipe fungsi). Siklus CPU untuk menegakkan varchar(n)hampir tidak penting. Gunakan batasan panjang saat Anda membutuhkannya . Dalam hal ini uuidadalah pemenang sebenarnya.
Erwin Brandstetter