Haruskah saya menambahkan batas panjang acak ke kolom VARCHAR?

35

Menurut dokumen PostgreSQL , tidak ada perbedaan kinerja antara VARCHAR, VARCHAR(n)dan TEXT.

Haruskah saya menambahkan batas panjang sewenang-wenang ke kolom nama atau alamat ?

Edit: Bukan duplikat dari:

Saya tahu CHARtipe ini adalah peninggalan masa lalu dan saya tertarik tidak hanya dalam kinerja tetapi pro dan kontra lainnya seperti Erwin menyatakan dalam jawaban yang luar biasa.

Daniel Serodio
sumber

Jawaban:

45

Jawabannya adalah tidak .
Jangan tambahkan pengubah panjang varcharjika Anda bisa menghindarinya. Sebagian besar waktu, Anda sebenarnya tidak membutuhkan batasan panjang. Cukup gunakan textuntuk semua data karakter. Buat itu varchar(tanpa pengubah panjang) jika Anda harus tetap kompatibel dengan RDBMS yang tidak memiliki text.

Kinerja hampir sama - textadalah sedikit lebih cepat dalam situasi langka , dan Anda menyimpan siklus untuk memeriksa panjang.

Jika Anda benar - benar perlu menegakkan panjang maksimum, masih menggunakan textdan menambahkan batasan pemeriksaan untuk itu:

ALTER TABLE tbl ADD CONSTRAINT tbl_col_len CHECK (length(col) < 51);

Anda dapat memodifikasi atau menjatuhkan batasan seperti itu kapan saja tanpa harus mengacaukan definisi tabel dan semua objek yang bergantung (tampilan, fungsi, kunci asing, ...)

Dengan pengubah panjang Anda hanya mengalami masalah seperti ini atau ini atau ini ...

PostgreSQL 9.1 memperkenalkan fitur baru untuk mengurangi rasa sakit. Saya mengutip catatan rilis di sini :

Izinkan ALTER TABLE ... SET DATA TYPEuntuk menghindari penulisan ulang tabel dalam kasus yang sesuai (Noah Misch, Robert Haas)

Misalnya, mengonversi varcharkolom ke teks tidak lagi membutuhkan penulisan ulang tabel. Namun, meningkatkan batasan panjang pada varcharkolom masih membutuhkan penulisan ulang tabel.

Erwin Brandstetter
sumber
Saya pikir jawaban ini akan jauh lebih baik jika itu hanya "tidak jangan tambahkan batasan sewenang-wenang ke database nyata." Saya merasa seperti banyak dari jawaban ini membutuhkan koreksi dan informasi lebih lanjut, tetapi itu benar-benar di luar topik dan akan mengalihkan perhatian dari kesimpulan Anda yang saya sepenuhnya setujui.
Evan Carroll
Ya, semua berdasarkan versi Postgres sebelum 9,1 - 6 tahun yang lalu. Sedikit berdebu sekarang, tetapi saran dasarnya masih bagus.
Erwin Brandstetter
Apakah ide yang baik atau buruk untuk menambahkan batasan pemeriksaan untuk setiap kolom teks untuk tujuan pemeriksaan kewarasan dan memastikan bug di klien tidak menggunakan semua ruang disk basis data dengan memasukkan teks yang sangat besar?
Kode
@ Kode: Ini adalah opsi yang layak. Jika Anda memiliki banyak kolom dengan batasan yang sama, pertimbangkan domain . Atau varchar(n)bagaimanapun juga, untuk kesederhanaan - jika kerugiannya biasanya tidak mempengaruhi Anda. (Batas tidak sewenang - wenang dalam kasus Anda jika Anda ingin menegakkan panjang maksimum aktual.)
Erwin Brandstetter
12

Jika Anda melihat batas panjang sebagai semacam batasan periksa untuk memastikan Anda memvalidasi data, maka ya tambahkan satu. Sebenarnya Anda mungkin ingin tidak menggunakan definisi panjang tetapi kendala cek nyata sebagai gantinya, untuk membuat mengubah batas lebih cepat.

Untuk mengubah (menambah) batas panjang, Anda perlu menjalankan ALTER TABLEyang mungkin membutuhkan waktu lama untuk menyelesaikan (karena kemungkinan penulisan ulang tabel) di mana diperlukan kunci meja eksklusif.

Mengubah (yaitu menjatuhkan dan menciptakan kembali) kendala pemeriksaan adalah operasi yang sangat singkat dan hanya membutuhkan membaca data tabel, itu tidak akan mengubah baris apa pun. Jadi itu akan menjadi jauh lebih cepat (yang pada gilirannya berarti kunci meja eksklusif akan ditahan untuk waktu yang jauh lebih singkat).

Selama operasi tidak ada perbedaan apapun antara a text, a varcharatau varchar(5000)kolom.

seekor kuda tanpa nama
sumber
Karena penasaran, mengapa menurut Anda pemeriksaan panjang ini tidak dapat dilakukan pada aplikasi klien saat mengambil data?
PirateApp
4
@ PirateApp: karena sangat sering akan ada lebih dari satu aplikasi atau sumber data eksternal (pikirkan impor batch malam). Dan hampir selalu database (dan data) hidup lebih lama dari satu aplikasi.
a_horse_with_no_name
2

Pertanyaannya secara khusus apakah menambahkan batas panjang arbitrer ke kolom VARCHAR?

Untuk itu, jawabannya hanyalah "tidak". Tidak ada yang dapat membenarkan penambahan batas arbitrer seperti yang Anda lakukan pada basis data inferior yang mendukung varchar(max)atau menggunakan konvensi varchar(255). Namun, jika spec membahas batasan, saya pikir jawabannya menjadi jauh lebih kompleks terutama pada versi modern PostgreSQL. Dan, untuk itu, saya akan condong ke arah YA .

Menurut pendapat saya, batasnya adalah pilihan bijak jika spec mengharuskannya. Terutama untuk beban kerja yang lebih masuk akal. Jika tanpa alasan lain maka untuk mempertahankan meta-data.

Dari jawaban saya di sini, kinerja indeks untuk CHAR vs VARCHAR (Postgres) , di mana saya membahas nilai meta-data.

Jika saya menemukan spesifikasi yang memiliki kunci teks panjang variabel yang bermakna dan saya percaya memiliki panjang maksimum konstan, saya akan menggunakan varcharjuga. Namun, saya tidak bisa memikirkan apa pun yang sesuai dengan kriteria itu.

Evan Carroll
sumber
1

Sepertinya ada beberapa perbedaan kinerja jika VARCHARdigunakan secara teratur untuk menyimpan string yang sangat besar, karena "string panjang dikompresi oleh sistem secara otomatis" dan "nilai yang sangat lama juga disimpan dalam tabel latar belakang." Secara teoritis ini berarti bahwa permintaan volume tinggi untuk bidang string yang sangat panjang akan lebih lambat daripada untuk bidang string pendek. Anda mungkin tidak akan pernah mengalami masalah ini, karena nama dan alamat tidak akan terlalu panjang.

Namun, tergantung pada bagaimana Anda menggunakan string ini di luar basis data Anda, Anda mungkin ingin menambahkan batas praktis untuk mencegah penyalahgunaan sistem. Misalnya, jika Anda menampilkan nama dan alamat pada formulir di suatu tempat, Anda mungkin tidak dapat menampilkan seluruh paragraf teks di bidang "nama", jadi masuk akal untuk membatasi kolom nama menjadi sekitar 500 karakter.

Edward
sumber
1
AFAIK tidak ada perbedaan dalam TOASTing varchar dan bidang teks.
dezso
VARCHARadalah gula sintaksis murni untuk TEXTdi Postgres, tidak ada perbedaan dalam penanganan penyimpanan; kompresi vs penyimpanan tabel latar belakang yang Anda sebutkan dilakukan berdasarkan pada panjang aktual data dalam kolom dan bukan pada metadata kolom. Kolom TEXT disimpan secara internal sebagai varlenaC struct (yang merupakan array panjang variabel dengan 4 byte pertama menyimpan panjang di buat / perbarui) dan ini adalah struct yang dioptimalkan berdasarkan panjangnya.
cowbert