Bagaimana bidang indeks INCLUDE besar akan mempengaruhi kinerja sistem?

15

Pertanyaan ini adalah tentang kinerja indeks SQL Server dengan varchar(2000)sebagai INCLUDEdalam indeks yang meliputi.

Saya mencoba untuk meningkatkan kinerja dalam aplikasi database yang lambat dan tidak stabil. Dalam beberapa kasus, data yang diakses melalui string varchar besar, dengan query termasuk operasi string multple seperti SUBSTRING(), SPACE(), dan DATALENGTH(). Berikut ini contoh akses yang disederhanakan;

update fattable set col3 =  
   SUBSTRING(col3,1,10) + '*' + 
   SUBSTRING(col3,12,DATALENGTH(col3)-12)
from fattable where substring(col3,10,1) = 'A' and col2 = 2

Skema terlihat seperti ini:

CREATE TABLE [dbo].[FatTable]( 
    [id] [bigint] IDENTITY(1,1) NOT NULL, 
    [col1] [nchar](12) NOT NULL, 
    [col2] [int] NOT NULL, 
    [col3] [varchar](2000) NOT NULL, ... 

Indeks berikut telah ditentukan, dengan bidang penutup pada kolom teks besar.

CREATE NONCLUSTERED INDEX [IndexCol2Col3] ON [dbo].[FatTable]  ( [col2] ASC ) 
    INCLUDE( [col3] )

Dari apa yang saya baca itu BAD untuk meletakkan bidang data besar dalam indeks. Saya telah membaca beberapa artikel, termasuk http://msdn.microsoft.com/en-us/library/ms190806.aspx yang membahas dampak ukuran halaman dan disk pada kinerja indeks. Ini dikatakan, rencana permintaan pasti menggunakan indeks penutup. Saya tidak memiliki informasi yang cukup untuk menentukan berapa sebenarnya biaya saya dalam hal beban sistem. Saya tahu bahwa secara keseluruhan, sistem berkinerja buruk, dan saya khawatir ini adalah salah satu masalah. Pertanyaan:

  • Apakah menempatkan varchar(2000)kolom ini dalam indeks INCLUDEmerupakan ide yang bagus?

  • Karena INCLUDEbidang disimpan dalam node daun, apakah mereka memiliki banyak dampak kinerja indeks?

Pembaruan: Terima kasih atas balasan yang sangat baik! Ini adalah pertanyaan yang tidak adil dalam beberapa hal - seperti yang Anda katakan, tidak ada jawaban benar mutlak tanpa statistik dan profil yang sebenarnya. Seperti banyak masalah kinerja, saya kira jawabannya adalah "itu tergantung".

RaoulRubin
sumber
Berapa lama nilai aktualnya? A VARCHAR(2000)yang biasanya menyimpan hanya sepuluh karakter adalah satu hal; 2.000 byte per rekaman yang solid adalah sesuatu yang lain.
Jon of All Trades
Hanya sebuah pengamatan: Sesuatu yang "berbau" di sini adalah bahwa kolom besar dapat berisi 1) teks bebas, di mana kueri dapat mengambil manfaat dari penulisan ulang untuk menggunakan indeks FULLTEXT atau 2) data kode yang "dapat dibaca manusia" (misalnya, cerdas lebar kunci, seperti VIN) yang dapat mengambil manfaat dari pemisahan menjadi kolom terpisah atau kolom terhitung yang bertahan dengan INDEKS. Dengan kata lain, aliran intelijen dan perubahan data tidak dirancang dengan baik.
Graeme
1
Ya #Graeme, ada bau busuk di sini - saya pikir itu disebut "warisan". Ada banyak masalah dalam database ini.
RaoulRubin

Jawaban:

14

Pernah merupakan kata yang besar, tetapi, secara umum, tidak, saya tidak akan menempatkan bidang varchar (2000) ke dalam TERMASUK.

Dan ya, cara data disimpan di tingkat halaman dapat berdampak serius pada kinerja indeks, tergantung pada bagaimana indeks digunakan.

Masalahnya adalah, semakin banyak baris data yang dapat Anda masukkan ke dalam sebuah halaman, semakin sedikit halaman yang harus diakses, semakin cepat sistem Anda, untuk sebagian besar. Menambahkan kolom yang sangat besar berarti lebih sedikit informasi yang disimpan pada sebuah halaman, jadi, jika rentang pencarian atau pemindaian, lebih banyak halaman harus dibaca untuk mengambil kembali data, dengan serius memperlambat hal-hal.

Untuk mengetahui dengan pasti apakah ini merupakan masalah pada kueri Anda, atau pada sistem Anda, Anda harus memantau bacaan, terutama jumlah halaman yang digunakan kueri.

Berikan Fritchey
sumber
Terima kasih, Grant. Seperti yang saya sebutkan komentar lain, info kinerja yang baik adalah langka, maka pertanyaan abstrak. Saya tidak punya pengalaman memantau biaya kinerja ukuran halaman. Firasat saya adalah bahwa itu adalah masalah, akan melihat apakah saya bisa mendapatkan beberapa statistik.
RaoulRubin
1
mengatur statistik IO selama kueri akan memberi tahu Anda banyak, pembacaan logis mewakili jumlah halaman yang diakses. Anda juga dapat memantau detik / membaca dari penghitung perfmon untuk mendapatkan info kinerja umum.
Grant Fritchey
6

Bisakah Anda meninjau kunci indeks yang dikelompokkan saat ini, dan mungkin membuat col2kunci indeks yang dikelompokkan sebagai gantinya? Dengan cara ini Anda mendapatkan perilaku 'sertakan' penutup (karena indeks berkerumun selalu 'termasuk' semuanya) tanpa menduplikasi data. Ini, tentu saja, tunduk pada banyak ifdan but, meskipun demikian mungkin layak dipertimbangkan. Tentu saja jika indeks cluster saat ini menegakkan batasan (kunci primer, unik) kata kendala harus dipindahkan ke indeks non-clustered.

Remus Rusanu
sumber
Saran Anda tentang PK adalah ide bagus, meskipun saya tidak akan bisa menerapkannya dalam kasus ini - PK yang ada diperlukan untuk pertanyaan lain. (Ini adalah teknik yang akan saya simpan di kotak peralatan!)
RaoulRubin
4

Sulit dijawab. Itu semua akan tergantung pada rasio baca: tulis Anda. Sudahkah Anda menguji beban kerja atau mensimulasikan seluruh siklus bisnis pada sistem pengujian, dengan dan tanpa kolom yang disertakan? Pencarian tanpa biaya mungkin banyak, tetapi jika Anda memperbarui data lebih sering daripada membacanya, itu mungkin ok.

Aaron Bertrand
sumber
Pembacaan keseluruhan vs pembaruan sebagian besar seimbang. Masalah organisasi dan privasi menyulitkan untuk mendapatkan statistik yang berguna dan tes realistis. Karena kita terbang kebanyakan buta, kita harus melihat hal-hal dari sudut pandang abstrak (maka pertanyaan ini). Pengujian akan berarti mendorong perubahan pada produksi dan mengamati hasil - sangat berisiko.
RaoulRubin
2
Dan apakah sebagian besar bacaan benar-benar menarik VARCHAR(2000)kolom ini , atau apakah Anda memecahkan masalah kinerja kueri yang sangat spesifik yang tidak mewakili sebagian besar kueri? Seperti yang disarankan Grant jika kolom ini tidak digunakan dalam banyak pertanyaan, atau benar-benar menyebabkan masalah untuk pencarian, mungkin akan lebih baik untuk membayar harga untuk pencarian ketika Anda membutuhkannya, tetapi tidak membayar penyimpanan ketika Anda tidak . Sekali lagi, sangat sulit untuk mengatakan di sisi mana Anda seharusnya berada, karena kami tidak benar-benar memiliki spesifikasi (dan bahkan lebih sulit karena Anda tidak dapat menguji - Anda harus berusaha untuk memperbaikinya).
Aaron Bertrand
3

Saya tahu saya terlambat untuk pesta ini, tetapi saya akan mengindeks persis ekspresi yang digunakan untuk mencari baris, seperti substring (col3,10,1). Jika seluruh col3 digunakan, saya akan mengindeks CHECKSUM (col3) (memahami bahwa mungkin saja ada tabrakan).

AK
sumber