Menggunakan teks MAX atau lebih spesifik, tipe lebih kecil

22

Seseorang sedang meninjau kode DDL saya untuk membuat tabel dan menyarankan, ketika mereka melihat saya melihat menggunakan VARCHAR(256)bidang untuk teks saya berharap menjadi sangat kecil, seperti nama depan atau apa pun, bahwa saya harus selalu menggunakan VARCHAR(MAX)dan ditautkan. Mengapa menggunakan sesuatu selain varchar (maks. ) . Saya membacanya tetapi sepertinya ketinggalan zaman, karena berfokus pada 2005, dan sepertinya tidak menawarkan justifikasi nyata untuk mengalokasikan hingga 2 GB per baris pada semua bidang teks.

Dari sudut pandang kinerja, penyimpanan, dll., Bagaimana sebaiknya seseorang memutuskan apakah akan menggunakan VARCHAR(MAX)atau jenis yang lebih spesifik yang lebih kecil untuk versi SQL Server modern? (misalnya, 2008, 2012, 2014)

Phrancis
sumber

Jawaban:

31

Haruskah saya selalu menggunakan (n)varchar(max)kolom teks?

Tidak.

Untuk SQL Server, maxtipe data hanya boleh ditentukan ketika tidak ada alternatif. Sebagai gantinya, seseorang harus memilih jenis pangkalan yang benar ( varcharatau nvarchar) dan menentukan panjang maksimum eksplisit yang sesuai dengan data yang akan disimpan.

Penyimpanan fisik identik apakah kolom tersebut diketik sebagai varchar(n)atau varchar(max), sehingga tidak menjadi perhatian.

Alasan untuk tidak memilih di (n)varchar(max)mana-mana berkisar pada fitur, kualitas rencana, dan kinerja.

Daftar lengkap mungkin tidak praktis, tetapi di antaranya, maxkolom:

fitur

  • Membutuhkan batasan terpisah untuk menegakkan panjang maksimum
  • Tidak dapat menjadi kunci dalam indeks (jadi tidak ada kendala unik juga)
  • Dapat mencegah DDL online (termasuk pembangunan kembali indeks dan menambahkan kolom bukan-nol yang baru)
  • Secara umum tidak didukung untuk fitur 'yang lebih baru' misalnya toko kolom
  • Lihat dokumentasi produk untuk fitur dan batasan yang lebih spesifik. Pola umum adalah bahwa ada batasan dan pembatasan canggung di sekitar maxtipe data. Tidak semua batasan dan efek samping didokumentasikan.

Performa

  • Memerlukan penanganan khusus dalam mesin eksekusi, untuk memperhitungkan ukuran yang berpotensi sangat besar. Biasanya, ini melibatkan penggunaan jalur kode yang kurang efisien, dengan antarmuka streaming
  • Mungkin memiliki konsekuensi yang tidak terduga serupa untuk kode eksternal (dan komponen SQL Server lainnya seperti SSIS), yang juga harus siap untuk menangani data hingga ukuran 2GB
  • Diasumsikan selebar 4000 byte dalam perhitungan hibah memori. Ini kemungkinan mengarah pada reservasi memori yang berlebihan, yang membatasi konkurensi, dan mendorong indeks dan halaman data yang berharga keluar dari memori cache
  • Nonaktifkan beberapa optimasi kinerja penting
  • Dapat memperpanjang durasi kunci
  • Dapat mencegah pengoptimal memilih rencana pencarian (non-dinamis)
  • Cegah filter didorong ke pemindaian dan cari sebagai residu
  • Dapat meningkatkan tekanan dan pertengkaran tempdb (tergantung versi), karena variabel dan parameter juga cenderung diketik maxuntuk mencocokkan definisi kolom

Singkatnya, ada begitu banyak efek samping yang halus (dan tidak diinginkan) dari penggunaan maxspecifier yang tidak perlu sehingga tidak masuk akal untuk melakukan ini. 'Kenyamanan' minor dalam menggunakan satu deklarasi bukanlah semacam kompensasi.

Evaluasi setiap jenis dalam konteks, gunakan jenis dasar yang benar ( varcharatau nvarchar), dan panjang eksplisit yang masuk akal.

Bacaan lebih lanjut:

Paul White mengatakan GoFundMonica
sumber
8

Ini akan dibaca seperti jawaban paranoid, tetapi tidak hanya pertimbangan penyimpanan dan kinerja.

Basis data itu sendiri tidak mengontrol kliennya, dan klien tidak dapat diasumsikan selalu memasukkan input pengguna dengan aman - bahkan jika basis data dirancang hanya untuk digunakan dengan aplikasi .net yang menggunakan Kerangka Entitas untuk merangkum transaksi dan memastikan pertanyaan parameterisasi digunakan secara sistematis, Anda tidak bisa tahu bahwa itu akan selalu menjadi masalah.

Saya tidak akan tahu persis bagaimana melakukan ini, tetapi dengan membuat semua bidang teks varchar(max), jika klien memiliki masalah Bobby Tables dan / atau parameter prosedur tersimpan Anda juga varchar(max), maka Anda membuatnya lebih mudah bagi penyerang untuk datang dengan nilai parameter jahat yang valid tetapi cerdik yang dapat melakukan hal-hal yang seharusnya tidak dilakukan klien - apa pun itu.

Dengan membatasi panjang untuk apa yang sebenarnya Anda butuhkan, Anda tidak melindungi diri dari serangan pintar ini (saya bahkan tidak yakin apa itu sebutan sebenarnya, saya hanya ingat membaca tentang itu beberapa waktu lalu), tetapi Anda tidak mengatakan " silakan, coba beri saya skrip 2GB untuk menjalankan "baik.

Mathieu Guindon
sumber
Apa namanya mungkin "injeksi" ("injeksi SQL", lebih khusus).
Andriy M
@ AndriyM ya, untuk beberapa alasan saya berpikir tentang serangan pemotongan SQL (MS tampaknya telah menghapus tautan yang telah saya tandai), tapi itu pada dasarnya mengeksploitasi varchar(not-max)parameter, jadi saya agak menjejakkan kaki di mulut saya di sini. Tapi ya injeksi SQL akan berlaku di sini. Mungkin saya harus mengulangi jawaban ini sedikit.
Mathieu Guindon