Apakah bidang "di luar baris" terbaca saat indeks berkerumun digunakan?

10

Saya tahu bahwa ketika VARCHAR(MAX)/NVARCHAR(MAX)kolom digunakan data disimpan out of the row- baris data akan memiliki pointer ke lokasi lain di mana 'nilai besar' disimpan.

Saya punya pertanyaan berikut:

  1. Apakah setiap bidang disimpan out of the rowatau hanya bidang max?
  2. Jika Anda menggunakan clustered indextabel untuk membaca seluruh catatan, apakah bidang yang disimpan di luar baris juga dibaca?

VARCHAR (MAX) atau NVARCHAR (MAX) dianggap sebagai 'tipe nilai besar'. Jenis nilai besar biasanya disimpan 'di luar baris'. Itu berarti ...

Gotqn
sumber
2
Dari mana bit terakhir yang dikutip berasal? Itu tidak benar.
Paul White 9
3
Teks lengkap di utas MSDN asli (oleh Jacob Sebastian) benar. "Kutipan" Stack Overflow kehilangan sedikit dari itu. Sebagian kecil dari yang Anda kutip di atas menghilangkan semua bit penting :)
Paul White 9

Jawaban:

13

Saya tahu bahwa ketika VARCHAR(MAX)/NVARCHAR(MAX)kolom digunakan, data disimpan di luar baris ...

Sebenarnya, itu tergantung pada pengaturan large value types out of rowopsi, yang dapat diatur menggunakan sp_tableoption. Dari dokumentasi :

Ekstrak BOL

The standar adalah untuk MAXnilai yang akan disimpan di baris , hingga 8000 byte, jika mereka cocok. Kecuali jika Anda telah terbiasa sp_tableoptionmengubah default, MAXdata Anda kemungkinan besar akan disimpan dalam baris.

Yang mengatakan, itu adalah praktik yang buruk untuk menggunakan MAXtipe data untuk nilai yang tidak akan pernah melebihi 8000 byte - sebagai gantinya gunakan tipe non-MAX. Selain dari yang lain, kinerja seringkali jauh lebih buruk ketika berhadapan dengan MAXtipe, karena SQL Server harus siap untuk menangani data yang mungkin berukuran hingga 2GB.

Apakah setiap bidang disimpan di luar baris atau hanya yang maks?

Hanya MAXyang. Selain itu, jika MAXkolom sebelumnya dalam baris dipindahkan dari baris, hanya kolom di baris itu yang terpengaruh. Itu diganti in-row oleh pointer ke struktur off-row LOB. Ada juga keadaan di mana kolom non-MAX dapat dipindahkan secara off-row.

Jika Anda menggunakan indeks berkerumun tabel untuk membaca seluruh catatan, apakah bidang yang disimpan di luar baris juga dibaca?

Memindai indeks yang dikelompokkan hanya melintasi data dalam baris. Jika data off-row diperlukan untuk query, itu dicari menggunakan pointer in-row.

Paul White 9
sumber
Apakah ini selalu benar - Scanning the clustered index traverses only in-row data.? Misalnya, jika Anda ingin menampilkan nilai NVARCHAR(MAX)bidang, bagaimana mungkin hanya bekerja dengan in-row-data(jika nilai disimpan di luar baris)? Atau ketika Anda menggunakan indeks berkerumun (karena tidak ada indeks penutup) tetapi Anda tidak akan workdengan NVARCHAR(MAX)bidang SQL Server cukup pintar untuk melihat itu dan melewatkan mencari out-of-rowdata?
Gotqn
Terima kasih atas jawabannya. Jadi, akhirnya, jika Anda memiliki dua kolom - intdan nvarchar(max)dan Anda memilih hanya intkolom, SQL-Server tidak menyia-nyiakan sumber daya untuk readitu out-of-rowdata seperti tahu Anda tidak akan menggunakannya?
Gotqn
Terima kasih banyak. Itu sangat bagus. Tampaknya, dengan menggunakan sp_tableoptionAnda dapat mengeluarkan semua tabel yang tidak sering digunakan untuk mengurangi ukuran baris, ketika banyak indeks berkerumun mencari / memindai dibuat.
Gotqn
3
@ gotqn Ya. Off-row adalah default untuk tipe LOB lama text, ntextdan image. Anda juga bisa menyimpan tipe besar dalam tabel terpisah, tentu saja.
Paul White 9
4

Perilaku ini untuk penyimpanan objek besar dapat dikontrol oleh pengaturan tabel:

exec sp_tableoption N'MyTable', 'large value types out of row', <'ON' or 'OFF'>

Referensi dalam dokumentasi SQL Server 2012 ada di: http://msdn.microsoft.com/en-us/library/ms173530.aspx

Oleh karena itu Anda dapat mengontrol di mana ruang digunakan, in-row atau disimpan di luar baris.

RLF
sumber
Terima kasih, saya benar-benar tidak tahu bahwa Anda dapat mengendalikan ini.
Gotqn