Apa yang terjadi selama sisipan "besar" di atas meja dengan kunci komposit berkerumun?

8

Pengetahuan SQL saya terbatas, jadi istilah yang akan saya gunakan kemungkinan besar bukan yang benar.

Saya memiliki tabel yang akan menyimpan hasil tes, untuk beberapa lokasi.

Pengujian akan direkam dalam database yang berbeda di lokasi yang berbeda (tidak ada koneksi jaringan) dan lokasi "master" akan secara teratur "mengimpor" hasil pengujian dari lokasi lain.

Saya berencana untuk memiliki kunci primer gabungan berkerumun di kolom LocationId (int) dan Date (datetime), dalam urutan itu. Alasannya adalah bahwa itu harus menjaga semua hasil untuk lokasi bersama dan saya hampir tidak akan pernah melakukan kueri berdasarkan rentang tanggal, melainkan oleh rentang tanggal dan lokasi.

Ukuran baris akan menjadi 80 hingga 100 byte dan jumlah hasil pengujian tidak boleh melebihi beberapa juta. "Impor" khas akan memasukkan 50 hingga 100 ribu hasil dari lokasi lain.

Apa yang akan terjadi selama impor? Apakah SQL "memindahkan" baris yang ada untuk mempertahankan pengelompokan, atau akan membiarkan tabel menjadi "terfragmentasi"? Apakah ini dapat menyebabkan kinerja yang besar jika impor dilakukan satu per satu? Haruskah saya lebih suka tidak repot dengan pemesanan baris dan hanya menambahkan kolom identitas sebagai kunci utama dan indeks pada kolom Tanggal untuk membantu dengan pertanyaan saya?

Sacha K
sumber

Jawaban:

19

Astaga, Anda punya banyak pertanyaan di sini. Mari kita hancurkan ini.

T: Apakah SQL "memindahkan" baris yang ada untuk mempertahankan pengelompokan, atau akan membiarkan tabel menjadi "terfragmentasi"?

Pikirkan sebuah basis data sebagai kumpulan halaman - potongan kertas literal yang diletakkan di meja Anda. Pikirkan kamus untuk saat ini. Jika Anda ingin menambahkan lebih banyak kata ke kamus, Anda dapat menambahkannya di tempat jika halaman memiliki ruang kosong.

Saat pertama kali memulai dengan kamus kosong, ini relatif mudah. Tetapi pikirkan kamus dewasa dengan ribuan halaman kertas di dalamnya, semuanya penuh.

Saat Anda ingin menambahkan lebih banyak kata ke kamus dewasa itu, kemungkinan besar tidak akan ada ruang tersisa di halaman. SQL Server akan "merobek" halaman - ia akan membawa halaman baru di tempat lain, dan memindahkan beberapa kata ke halaman baru itu. Halaman baru akan berada di akhir kamus. Berita baiknya adalah segera setelah tindakan itu, sekarang ada halaman yang setengah kosong di akhir kamus Anda, dan juga di tengah, keduanya dengan ruang untuk menambahkan kata-kata.

Jika Anda menambahkannya dalam urutan itu, itu adalah. (Inilah mengapa cara Anda memuat data menjadi semakin penting.)

Apakah ini dapat menyebabkan kinerja yang besar jika impor dilakukan satu per satu?

Lupakan indeks selama satu detik - menambahkan data satu baris pada satu waktu sama sekali tidak efisien terlepas dari struktur indeks. SQL Server adalah sistem berbasis set - kapan pun Anda dapat bekerja dalam set, Anda mungkin harus melakukannya.

Apa yang terjadi ketika saya meminta data?

Anda tidak menanyakan ini, tapi saya memintanya untuk Anda, hahaha.

Pikirkan kembali tentang akibat dari sisipan kita. Sekarang kita punya kamus yang sebagian besar dipesan, tetapi ketika Anda sampai ke beberapa titik kamus, Anda harus melompat ke belakang untuk membaca dari beberapa halaman lain. Jika semua halaman ini di-cache dalam memori Anda (RAM, buffer pool, dll) maka overhead tidak akan sebesar itu. Sebagian besar akses memori adalah acak - tidak seperti SQL Server menyimpan kamus Anda dalam memori secara berurutan.

Di sisi lain, jika Anda perlu mengambil data dari hard drive magnetik konvensional (karat berputar), maka Anda bisa mendapatkan sedikit manfaat kinerja jika data tersebut disimpan secara berurutan. Tujuan desain sebenarnya di sini, adalah untuk mendapatkan data dari RAM alih-alih mendapatkannya dari drive. Perbedaan antara defragmented data pada disk versus data terfragmentasi pada disk sama sekali tidak sepenting perbedaan antara mendapatkannya dari disk versus mendapatkannya dari RAM .

Haruskah saya lebih suka tidak repot dengan pemesanan baris dan hanya menambahkan kolom identitas sebagai kunci utama dan indeks pada kolom Tanggal untuk membantu dengan pertanyaan saya?

Bingo: ini adalah perbedaan antara desain database fisik dan desain database logis. Programmer harus khawatir banyak tentang desain database fisik pada awalnya, tetapi selama database Anda di bawah, katakanlah, ukuran 100GB, Anda dapat memperbaiki desain logis dalam posting, sehingga untuk berbicara. Letakkan bidang identitas di sana sebagai permulaan, klaster di atasnya, dan kemudian setelah ditayangkan selama beberapa bulan, kunjungi kembali desain indeks untuk memaksimalkan kinerja.

Sekarang, setelah mengatakan itu, setelah Anda berpengalaman dengan jenis pengambilan keputusan ini, maka Anda akan lebih siap untuk menebak indeks angka sejak awal. Meski begitu, saya bahkan tidak terlalu memikirkan desain indeks pada awalnya. Pengguna sepertinya tidak pernah menanyakan data seperti yang saya harapkan.

Brent Ozar
sumber
1
Sisipan satu per satu adalah pertanyaan teoretis. Tampak meragukan bagi saya, kinerja bijaksana, bahwa "baris disimpan secara fisik pada disk dalam urutan yang sama dengan indeks berkerumun" seperti yang Anda baca di sebagian besar tempat.
Sacha K
Saya akan pergi untuk kolom identitas. Data akan ditambahkan "di akhir" dan secara alami diurutkan berdasarkan tanggal. Tanggal yang sama untuk lokasi yang berbeda tidak akan "berdekatan" tetapi itu tidak masalah bagi saya.
Sacha K