Saya sedang mengerjakan basis data untuk aplikasi web kecil di sekolah saya menggunakan SQL Server 2005
.
Saya melihat beberapa aliran pemikiran tentang masalah varchar
vs nvarchar
:
- Gunakan
varchar
kecuali Anda berurusan dengan banyak data yang diinternasionalkan, kemudian gunakannvarchar
. - Cukup gunakan
nvarchar
untuk semuanya.
Saya mulai melihat manfaat dari tampilan 2. Saya tahu bahwa nvarchar memang memakan ruang dua kali lebih banyak, tetapi itu tidak selalu merupakan masalah besar karena ini hanya akan menyimpan data untuk beberapa ratus siswa. Bagi saya sepertinya akan lebih mudah untuk tidak khawatir tentang hal itu dan biarkan semuanya menggunakan nvarchar. Atau ada sesuatu yang saya lewatkan?
sql-server
sql-server-2005
storage
varchar
nvarchar
Jason Baker
sumber
sumber
NVARCHAR
", dan dapat memiliki dampak yang sangat negatif pada kinerja dan biaya / anggaran perangkat keras. Beberapa baris, bahkan beberapa ribu, tidak masalah. Tetapi sistem tumbuh lebih cepat dari yang diharapkan orang, sehingga jawaban yang diterima saat ini adalah merugikan masyarakat. Terima kasih.Jawaban:
Selalu gunakan nvarchar.
Anda mungkin tidak pernah memerlukan karakter bita ganda untuk sebagian besar aplikasi. Namun, jika Anda perlu mendukung bahasa bita-ganda dan Anda hanya memiliki dukungan bita-tunggal dalam skema basis data Anda, sangat mahal untuk kembali dan memodifikasi seluruh aplikasi Anda.
Biaya migrasi satu aplikasi dari varchar ke nvarchar akan jauh lebih banyak daripada sedikit ruang disk tambahan yang akan Anda gunakan di sebagian besar aplikasi.
sumber
Disk space bukan masalah ... tetapi memori dan kinerja akan. Gandakan halaman yang dibaca, ukuran indeks ganda, LIKE aneh dan = perilaku konstan dll
Apakah Anda perlu menyimpan skrip Cina dll? Ya atau tidak...
Dan dari MS BOL " Penyimpanan dan Efek Kinerja dari Unicode "
Edit :
Pertanyaan SO terbaru yang menyoroti seberapa buruk kinerja nvarchar ...
SQL Server menggunakan CPU tinggi ketika mencari di dalam string nvarchar
sumber
Bersikaplah konsisten! BERGABUNG dengan VARCHAR ke NVARCHAR memiliki kinerja yang luar biasa.
sumber
nvarchar
denganvarchar
vs mengkonversinvarchar
kevarchar
dan bergabung denganvarchar
. Kecuali tentu saja Anda berarti konsisten dalam tipe data kolom, bukan bergabung.VARCHAR
danNVARCHAR
, itu harus karena pengindeksanVARCHAR
kolom bersama dengan jenis Kolasi yang digunakan untuk kolom itu (dan karenanya indeks). Saya membahas topik ini secara rinci dalam posting blog berikut: Dampak pada Indeks Saat Memadukan Jenis VARCHAR dan NVARCHAR .nvarchar akan memiliki overhead yang signifikan dalam memori, penyimpanan, set kerja dan pengindeksan, jadi jika spesifikasi menentukan bahwa itu benar-benar tidak akan pernah diperlukan, jangan repot-repot.
Saya tidak akan memiliki aturan "selalu nvarchar" yang keras dan cepat karena dapat menjadi pemborosan dalam banyak situasi - terutama ETL dari ASCII / EBCDIC atau pengidentifikasi dan kolom kode yang sering berupa kunci dan kunci asing.
Di sisi lain, ada banyak kasus kolom, di mana saya pasti akan menanyakan pertanyaan ini lebih awal dan jika saya tidak segera mendapatkan jawaban yang sulit dan cepat, saya akan membuat kolom nvarchar.
sumber
Saya ragu untuk menambahkan jawaban lain di sini karena sudah ada beberapa, tetapi beberapa poin perlu dibuat yang belum dibuat atau belum dibuat dengan jelas.
Pertama: Do tidak selalu menggunakan
NVARCHAR
. Itu adalah sikap / pendekatan yang sangat berbahaya, dan seringkali mahal. Dan tidak ada yang lebih baik untuk mengatakan " Jangan pernah menggunakan kursor" karena mereka kadang-kadang merupakan cara paling efisien untuk menyelesaikan masalah tertentu, dan kerja sama yang umum dalam melakukanWHILE
loop hampir selalu lebih lambat daripada Kursor yang dilakukan dengan benar .Satu-satunya waktu Anda harus menggunakan istilah "selalu" adalah ketika menasihati untuk "selalu melakukan yang terbaik untuk situasi". Memang itu seringkali sulit untuk ditentukan, terutama ketika mencoba menyeimbangkan keuntungan jangka pendek dalam waktu pengembangan (manajer: "kami membutuhkan fitur ini - yang belum Anda ketahui sampai sekarang - seminggu yang lalu!") Dengan lama biaya pemeliharaan jangka panjang (manajer yang awalnya menekan tim untuk menyelesaikan proyek 3 bulan dalam sprint 3 minggu: "mengapa kita mengalami masalah kinerja ini? Bagaimana mungkin kita melakukan X yang tidak memiliki fleksibilitas? Kita tidak mampu satu atau dua sprint untuk memperbaikinya. Apa yang bisa kita lakukan dalam seminggu sehingga kita bisa kembali ke item prioritas kita? Dan kita pasti perlu menghabiskan lebih banyak waktu dalam desain sehingga ini tidak terus terjadi! ").
Kedua: jawaban @ gbn menyentuh beberapa poin yang sangat penting untuk dipertimbangkan ketika membuat keputusan pemodelan data tertentu ketika jalurnya tidak 100% jelas. Tetapi ada lebih banyak untuk dipertimbangkan:
Pemborosan ruang memiliki efek kaskade besar pada seluruh sistem. Saya menulis artikel yang menjelaskan secara rinci tentang topik ini: Disk Is Cheap! ORLY? (diperlukan pendaftaran gratis; maaf saya tidak mengendalikan kebijakan itu).
Ketiga: Sementara beberapa jawaban salah berfokus pada aspek "ini adalah aplikasi kecil", dan beberapa benar menyarankan untuk "menggunakan apa yang sesuai", tidak ada jawaban yang memberikan panduan nyata kepada OP. Rincian penting yang disebutkan dalam Pertanyaan adalah bahwa ini adalah halaman web untuk sekolah mereka. Bagus! Jadi kami dapat menyarankan bahwa:
NVARCHAR
sejak, dari waktu ke waktu, itu hanya mendapatkan lebih mungkin bahwa nama-nama dari budaya lain akan muncul di tempat-tempat.VARCHAR
dengan Halaman Kode yang sesuai (yang ditentukan dari Collation of the field).INT
/TINYINT
karena kode ISO panjangnya tetap, dapat dibaca oleh manusia, dan baik, standar :) gunakanCHAR(2)
untuk dua kode huruf danCHAR(3)
jika menggunakan 3 kode huruf. Dan pertimbangkan untuk menggunakan Kolasi biner sepertiLatin1_General_100_BIN2
.VARCHAR
karena merupakan standar internasional untuk tidak pernah menggunakan huruf apa pun di luar AZ. Dan ya, masih menggunakanVARCHAR
bahkan jika hanya menyimpan kode pos AS dan bukan INT karena kode pos bukan angka, mereka adalah string, dan beberapa dari mereka memiliki "0" terdepan. Dan pertimbangkan untuk menggunakan Kolasi biner sepertiLatin1_General_100_BIN2
.NVARCHAR
karena keduanya sekarang dapat berisi karakter Unicode.Keempat: Sekarang Anda memiliki
NVARCHAR
data yang menggunakan ruang dua kali lebih banyak daripada yang dibutuhkan untuk data yang cocok dengan baikVARCHAR
("cocok dengan baik" = tidak berubah menjadi "?") Dan entah bagaimana, seolah-olah dengan sihir, aplikasi tumbuh dan sekarang ada jutaan catatan di setidaknya satu dari bidang ini di mana sebagian besar baris adalah ASCII standar tetapi beberapa berisi karakter Unicode sehingga Anda harus menyimpannyaNVARCHAR
, pertimbangkan yang berikut ini:Jika Anda menggunakan SQL Server 2008 - 2016 RTM dan pada Enterprise Edition, ATAU jika menggunakan SQL Server 2016 SP1 (yang membuat Kompresi Data tersedia di semua edisi) atau lebih baru, maka Anda dapat mengaktifkan Kompresi Data . Kompresi Data dapat (tetapi tidak akan "selalu") mengompresi data Unicode di dalam
NCHAR
danNVARCHAR
bidang. Faktor penentu adalah:NCHAR(1 - 4000)
danNVARCHAR(1 - 4000)
gunakan Skema Kompresi Standar untuk Unicode , tetapi hanya dimulai pada SQL Server 2008 R2, DAN hanya untuk data ROW, bukan OVERFLOW! Ini tampaknya lebih baik daripada algoritma kompresi ROW / PAGE biasa.NVARCHAR(MAX)
danXML
(dan saya kira jugaVARBINARY(MAX)
,,TEXT
danNTEXT
) data yang DALAM ROW (bukan baris di halaman LOB atau OVERFLOW) setidaknya dapat dikompresi HALAMAN, tetapi tidak dikompresi ROW. Tentu saja, kompresi PAGE tergantung pada ukuran nilai in-row: Saya diuji dengan VARCHAR (MAX) dan melihat bahwa 6000 karakter / baris byte tidak akan dikompres, tetapi 4000 karakter / byte baris melakukannya.Jika menggunakan SQL Server 2005, atau 2008 - 2016 RTM dan bukan pada Enterprise Edition, Anda dapat memiliki dua bidang: satu
VARCHAR
dan satuNVARCHAR
. Misalnya, Anda menyimpan URL yang sebagian besar merupakan karakter ASCII dasar (nilai 0 - 127) dan karenanya cocokVARCHAR
, tetapi terkadang memiliki karakter Unicode. Skema Anda dapat mencakup 3 bidang berikut:Dalam model ini, Anda hanya PILIH dari
[URL]
kolom yang dihitung. Untuk memasukkan dan memperbarui, Anda menentukan bidang mana yang akan digunakan dengan melihat apakah mengubah mengubah nilai yang masuk, yang harusNVARCHAR
bertipe:Anda dapat GZIP nilai yang masuk ke
VARBINARY(MAX)
dan kemudian unzip di jalan keluar:COMPRESS
danDECOMPRESS
fungsi, yang juga GZip.Jika menggunakan SQL Server 2017 atau yang lebih baru, Anda bisa melihat membuat tabel Clustered Columnstore Index.
Meskipun ini bukan opsi yang layak, SQL Server 2019 memperkenalkan dukungan asli untuk UTF-8 di
VARCHAR
/CHAR
tipe data. Saat ini ada terlalu banyak bug untuk digunakan, tetapi jika mereka diperbaiki, maka ini merupakan opsi untuk beberapa skenario. Silakan lihat posting saya, " Dukungan Asli UTF-8 di SQL Server 2019: Juruselamat atau Nabi Palsu? ", Untuk analisis terperinci dari fitur baru ini.sumber
Untuk aplikasi Anda, nvarchar baik-baik saja karena ukuran basis datanya kecil. Mengatakan "selalu gunakan nvarchar" adalah penyederhanaan besar. Jika Anda tidak diharuskan menyimpan hal-hal seperti Kanji atau karakter gila lainnya, gunakan VARCHAR, itu akan menggunakan ruang yang jauh lebih sedikit. Pendahulu saya di pekerjaan saya saat ini merancang sesuatu menggunakan NVARCHAR ketika itu tidak diperlukan. Kami baru-baru ini beralih ke VARCHAR dan menyimpan 15 GB hanya pada tabel itu (sangat ditulis untuk). Selanjutnya, jika Anda kemudian memiliki indeks pada tabel itu dan Anda ingin memasukkan kolom itu atau membuat indeks komposit, Anda baru saja membuat ukuran file indeks Anda lebih besar.
Hanya bijaksana dalam keputusan Anda; dalam pengembangan SQL dan definisi data tampaknya jarang ada "jawaban default" (selain menghindari kursor di semua biaya, tentu saja).
sumber
Karena aplikasi Anda kecil, pada dasarnya tidak ada kenaikan biaya yang cukup besar untuk menggunakan nvarchar di atas varchar, dan Anda menyelamatkan diri dari potensi sakit kepala di jalan jika Anda perlu menyimpan data unicode.
sumber
Secara umum; Mulailah dengan tipe data paling mahal yang memiliki kendala paling sedikit. Masukkan ke dalam produksi . Jika kinerja mulai menjadi masalah, cari tahu apa yang sebenarnya disimpan di
nvarchar
kolom tersebut. Apakah ada karakter di sana yang tidak cocokvarchar
? Jika tidak, beralihlah ke varchar. Jangan mencoba melakukan pra-optimalisasi sebelum Anda tahu di mana rasa sakitnya. Dugaan saya adalah bahwa pilihan antara nvarchar / varchar bukanlah yang akan memperlambat aplikasi Anda di masa mendatang. Akan ada bagian lain dari aplikasi di mana penyetelan kinerja akan memberi Anda lebih banyak keuntungan .sumber
Selama beberapa tahun terakhir semua proyek kami telah menggunakan NVARCHAR untuk semuanya, karena semua proyek ini multibahasa. Data yang diimpor dari sumber eksternal (misalnya file ASCII, dll.) Dikonversi ke Unicode sebelum dimasukkan ke dalam database.
Saya belum pernah menemukan masalah terkait kinerja dari indeks yang lebih besar, dll. Indeks memang menggunakan lebih banyak memori, tetapi memori itu murah.
Apakah Anda menggunakan prosedur tersimpan atau membuat SQL on the fly, pastikan semua konstanta string diawali dengan N (mis. SET @foo = N'Hello world. ';) Sehingga konstanta juga Unicode. Ini menghindari konversi tipe string apa pun pada saat runtime.
YMMV.
sumber
Saya dapat berbicara dari pengalaman tentang hal ini, waspadalah
nvarchar
. Kecuali Anda benar-benar membutuhkannya, bidang data ini merusak kinerja pada basis data yang lebih besar. Saya mewarisi database yang menyakitkan dalam hal kinerja dan ruang. Kami dapat mengurangi basis data 30GB sebesar 70%! Ada beberapa modifikasi lain yang dibuat untuk membantu dengan kinerja tetapi saya yakinvarchar
itu membantu secara signifikan dengan itu juga. Jika database Anda memiliki potensi untuk menumbuhkan tabel hingga sejuta + catatan, jauhinvarchar
semua biaya.sumber
Saya sering menangani pertanyaan ini di tempat kerja:
Umpan inventaris dan harga FTP - Deskripsi item dan teks lainnya berada di nvarchar saat varchar berfungsi dengan baik. Mengubah ini ke varchar mengurangi ukuran file hampir setengah dan sangat membantu dengan unggahan.
Skenario di atas bekerja dengan baik sampai seseorang memasukkan karakter khusus dalam deskripsi item (mungkin merek dagang, tidak dapat mengingat)
Saya masih tidak menggunakan nvarchar setiap kali melalui varchar. Jika ada keraguan atau potensi untuk karakter khusus, saya menggunakan nvarchar. Saya menemukan saya menggunakan varchar sebagian besar ketika saya dalam kendali 100% dari apa yang mengisi bidang.
sumber
Mengapa, dalam semua diskusi ini, tidak disebutkan UTF-8? Mampu menyimpan rentang unicode penuh karakter tidak berarti kita harus selalu mengalokasikan dua-byte-per-karakter (atau "titik kode" untuk menggunakan istilah UNICODE). Semua ASCII adalah UTF-8. Apakah SQL Server memeriksa bidang VARCHAR () yang teksnya ketat ASCII (yaitu bit byte atas nol)? Saya harap tidak.
Jika kemudian Anda ingin menyimpan unicode dan ingin kompatibilitas dengan aplikasi ASCII-satunya yang lebih tua, saya akan berpikir menggunakan VARCHAR () dan UTF-8 akan menjadi peluru ajaib: Itu hanya menggunakan lebih banyak ruang ketika perlu.
Bagi Anda yang tidak terbiasa dengan UTF-8, mungkin saya merekomendasikan primer .
sumber
N
tipe XML dan -prefixed). Anda tidak mendapatkan pilihan menggunakan UTF-8. Juga, pengkodean Unicode (UTF-8, UCS-2 / UTF-16, dan UTF-32) tidak dapat diterapkan ke bidang VARCHAR.Akan ada contoh luar biasa ketika Anda ingin secara sengaja membatasi tipe data untuk memastikan itu tidak mengandung karakter dari set tertentu. Sebagai contoh, saya memiliki skenario di mana saya perlu menyimpan nama domain dalam database. Internasionalisasi untuk nama domain tidak dapat diandalkan pada saat itu sehingga lebih baik untuk membatasi input di tingkat dasar, dan membantu menghindari masalah potensial.
sumber
Jika Anda menggunakan
NVARCHAR
hanya karena prosedur yang disimpan oleh sistem memerlukannya, kejadian yang paling sering terjadi adalah tidak dapat dijelaskansp_executesql
, dan SQL dinamis Anda sangat panjang, Anda akan lebih baik dari perspektif kinerja melakukan semua manipulasi string (penggabungan, penggantian dll.)VARCHAR
Kemudian mengonversi hasil akhirNVARCHAR
dan memasukkannya ke dalam parameter proc. Jadi tidak, jangan selalu gunakanNVARCHAR
!sumber