Persyaratan umum dalam ETL dan berbagai skenario pelaporan adalah memuat tabel staging SQL Server secara diam-diam di latar belakang, sehingga pengguna yang menanyakan data tidak terpengaruh oleh penulisan dan sebaliknya. Triknya adalah bagaimana dan kapan Anda mengarahkan pengguna ke versi data yang baru dan diperbarui.
Contoh Sederhana Tabel Pementasan:Analogi Pasar Petani
Jadi, apa itu tabel pementasan dalam SQL? Meja pementasan dapat lebih mudah dipahami dengan menggunakan contoh dunia nyata:Katakanlah Anda memiliki meja penuh dengan sayuran yang Anda jual di pasar petani setempat. Saat sayuran Anda terjual dan Anda membawa inventaris baru:
- Saat Anda membawa banyak sayuran baru, Anda perlu waktu 20 menit untuk membersihkan meja dan mengganti stok yang tersisa dengan produk yang lebih baru.
- Anda tidak ingin pelanggan duduk di sana dan menunggu 20 menit untuk pergantian terjadi, karena sebagian besar akan mendapatkan sayuran mereka di tempat lain.
Sekarang, bagaimana jika Anda memiliki meja kosong kedua tempat Anda memuat sayuran baru, dan saat Anda melakukannya, pelanggan masih dapat membeli sayuran lama dari meja pertama? (Mari kita berpura-pura bukan karena sayuran yang lebih tua menjadi busuk atau kurang diminati.)
Menyegarkan Tabel di SQL Server
Ada beberapa metode untuk memuat ulang seluruh tabel saat sedang aktif dikueri; dua dekade lalu, saya mengambil keuntungan tak terkendali dari sp_rename
— Saya akan memainkan permainan shell dengan salinan bayangan kosong dari tabel, dengan senang hati memuat ulang salinan bayangan dan kemudian hanya melakukan penggantian nama di dalam transaksi.
Di SQL Server 2005, saya mulai menggunakan skema untuk menyimpan salinan bayangan tabel yang saya transfer menggunakan teknik permainan shell yang sama, yang saya tulis di dua posting ini:
- Tembakan Trik:Skema Switch-a-Roo
- Skema Switch-a-Roo, Bagian 2
Satu-satunya keuntungan mentransfer objek antar skema daripada mengganti namanya adalah tidak ada pesan peringatan tentang mengganti nama objek – yang bahkan bukan masalah, kecuali pesan peringatan mengisi log riwayat agen yang jauh lebih cepat.
Kedua pendekatan masih memerlukan kunci modifikasi skema (Sch-M), sehingga mereka harus menunggu transaksi yang ada untuk melepaskan kunci mereka sendiri. Setelah mendapatkan kunci Sch-M, mereka memblokir kueri berikutnya yang memerlukan kunci stabilitas skema (Sch-S)… yang hampir setiap kueri. Ini dapat dengan cepat menjadi mimpi buruk rantai pemblokiran, karena setiap kueri baru yang membutuhkan Sch-S harus mengantre di belakang Sch-M. (Dan tidak, Anda tidak dapat menyiasatinya dengan menggunakan RCSI atau NOLOCK
di mana-mana, karena bahkan pertanyaan itu masih membutuhkan Sch-S. Anda tidak dapat memperoleh Sch-S dengan Sch-M di tempatnya, karena keduanya tidak kompatibel—Michael J. Swart membicarakannya di sini.)
Kendra Little benar-benar membuka mata saya tentang bahaya transfer skema dalam postingannya, “Data Pementasan:Mengunci Bahaya dengan ALTER SCHEMA TRANSFER.” Di sana dia menunjukkan mengapa transfer skema bisa lebih buruk daripada mengganti nama. Dia kemudian merinci cara ketiga dan jauh lebih tidak berdampak untuk menukar tabel, yang sekarang saya gunakan secara eksklusif:perpindahan partisi. Metode ini memungkinkan sakelar untuk menunggu pada prioritas yang lebih rendah, yang bahkan bukan merupakan opsi dengan teknik penggantian nama atau transfer skema. Joe Sack menjelaskan secara rinci tentang peningkatan ini yang ditambahkan kembali di SQL Server 2014:"Menjelajahi Opsi Tunggu Kunci Prioritas Rendah di SQL Server 2014 CTP1."
Contoh Pengalihan Partisi SQL Server
Mari kita lihat contoh dasarnya, mengikuti intisari menyeluruh Kendra di sini. Pertama, kita akan membuat dua database baru:
BUAT DATABASE NewWay;BUAT DATABASE OldWay;GO
Di database baru, kami akan membuat tabel untuk menyimpan inventaris sayuran kami, dan dua salinan tabel untuk permainan cangkang kami:
GUNAKAN NewWay;GO CREATE TABLE dbo.Vegetables_NewWay( VegetableID int, Name sysname, WhenPicked datetime, BackStory nvarchar(max));GO -- kita perlu membuat dua salinan tambahan dari tabel. CREATE TABLE dbo.Vegetables_NewWay_prev( VegetableID int, Name sysname, WhenPicked datetime, BackStory nvarchar(max));GO CREATE TABLE dbo.Vegetables_NewWay_hold( VegetableID int, Name sysname, WhenPicked datetime, BackStory n));GO Kami membuat prosedur yang memuat salinan staging dari tabel, kemudian menggunakan transaksi untuk mengganti salinan saat ini.BUAT PROSEDUR dbo.DoTheVeggieSwap_NewWayASBEGIN AKTIFKAN NOCOUNT; TRUNCATE TABLE dbo.Vegetables_NewWay_prev; INSERT dbo.Vegetables_NewWay_prev SELECT TOP (1000000) s.session_id, o.name, s.last_successful_logon, LEFT(m.definition, 500) FROM sys.dm_exec_sessions AS s LINTAS GABUNG model.sys.all_objects SEBAGAI all_sql_modules AS m ON o.[object_id] =m.[object_id]; -- perlu mengambil kunci Sch-M di sini:MULAI TRANSAKSI; ALTER TABLE dbo.Vegetables_NewWay BERALIH KE dbo.Vegetables_NewWay_hold WITH (WAIT_AT_LOW_PRIORITY (MAX_DURATION =1 MINUTES, ABORT_AFTER_WAIT =BLOCKERS)); ALTER TABLE dbo.Vegetables_NewWay_prev BERALIH KE dbo.Vegetables_NewWay; KOMITMEN TRANSAKSI; -- dan sekarang pengguna akan meminta data baru di dbo -- dapat mengganti salinan lama kembali dan memotongnya -- tanpa mengganggu kueri lain ALTER TABLE dbo.Vegetables_NewWay_hold BERALIH KE dbo.Vegetables_NewWay_prev; TRUNCATE TABLE dbo.Vegetables_NewWay_prev;ENDGOKeindahan
WAIT_AT_LOW_PRIORITY
adalah Anda dapat sepenuhnya mengontrol perilaku denganABORT_AFTER_WAIT
pilihan:
ABORT_AFTER_WAIT setelan | Deskripsi / gejala |
---|---|
MANDIRI | Ini berarti saklar akan menyerah setelah n menit. Untuk sesi yang mencoba melakukan peralihan, ini akan muncul sebagai pesan kesalahan: Batas waktu permintaan kunci terlampaui. |
BLOCKERS | Ini menentukan sakelar akan menunggu hingga n menit, lalu memaksakan diri ke garis depan dengan membunuh semua pemblokir di depannya . Sesi yang mencoba berinteraksi dengan tabel yang terbentur oleh operasi sakelar akan melihat beberapa kombinasi dari pesan kesalahan ini: Sesi Anda telah terputus karena operasi DDL prioritas tinggi.Tidak dapat melanjutkan eksekusi karena sesi dalam status mematikan. Terjadi kesalahan parah pada perintah saat ini. Hasilnya, jika ada, harus dibuang. |
TIDAK ADA | Ini menyatakan bahwa sakelar akan dengan senang hati menunggu sampai mendapat gilirannya, terlepas dari MAX_DURATION .
Ini adalah perilaku yang sama yang Anda dapatkan dengan penggantian nama, transfer skema, atau sakelar partisi tanpa |
BLOCKERS
opsi bukanlah cara yang paling ramah untuk menangani berbagai hal, karena Anda sudah mengatakan tidak apa-apa melalui operasi pementasan/pengalihan ini bagi pengguna untuk melihat data yang sedikit ketinggalan zaman. Saya mungkin lebih suka menggunakan SELF
dan operasikan coba lagi jika tidak bisa mendapatkan kunci yang diperlukan dalam waktu yang ditentukan. Saya akan melacak seberapa sering gagal, terutama kegagalan berturut-turut, karena Anda ingin memastikan data tidak pernah menjadi terlalu basi.
Dibandingkan dengan Cara Lama Beralih Antar Skema
Begini cara saya menangani peralihan sebelumnya:
GUNAKAN OldWay;GO -- buat dua skema dan dua salinan tabel CREATE SCHEMA prev AUTHORIZATION dbo;GO CREATE SCHEMA hold AUTHORIZATION dbo;GO CREATE TABLE dbo.Vegetables_OldWay( VegetableID int, Name sysname, WhenPicked datetime, BackStory max));GO CREATE TABLE prev.Vegetables_OldWay( VegetableID int, Name sysname, WhenPicked datetime, BackStory nvarchar(max));GO CREATE PROCEDURE dbo.DoTheVeggieSwap_OldWayASBEGIN SET NOCOUNT ON; TRUNCATE TABLE prev.Vegetables_OldWay; INSERT prev.Vegetables_OldWay PILIH TOP (1000000) s.session_id, o.name, s.last_successful_logon, LEFT(m.definition, 500) FROM sys.dm_exec_sessions AS s LINTAS GABUNG model.sys.all_objects GABUNG SEBAGAI model. all_sql_modules AS m ON o.[object_id] =m.[object_id]; -- perlu mengambil kunci Sch-M di sini:MULAI TRANSAKSI; ALTER SCHEMA tahan TRANSFER dbo.Vegetables_OldWay; ALTER SKEMA TRANSFER dbo sebelumnya.Vegetables_OldWay; KOMITMEN TRANSAKSI; -- dan sekarang pengguna akan menanyakan data baru di dbo -- dapat mentransfer salinan lama kembali dan memotongnya tanpa -- mengganggu kueri lain:ALTER SCHEMA prev TRANSFER hold.Vegetables_OldWay; TRUNCATE TABLE sebelumnya.Vegetables_OldWay;ENDGO
Saya menjalankan tes konkurensi dengan menggunakan dua jendela SQLQueryStress Erik Ejlskov Jensen:satu untuk mengulang panggilan ke prosedur setiap menit, dan yang lainnya untuk menjalankan 16 utas seperti ini, ribuan kali:
MULAI TRANSAKSI; UPDATE TOP (1) dbo.
Durasi dan Tingkat Kesalahan | Transfer Skema | ABORT_AFTER_WAIT: SELF | ABORT_AFTER_WAIT: BLOCKERS |
---|---|---|---|
Durasi Rata-Rata – Transfer/Beralih | 96,4 detik | 68,4 detik | 20.8 detik |
Durasi Rata-Rata – DML | 18,7 detik | 2,7 detik | 2,9 detik |
Pengecualian – Transfer/Beralih | 0 | 0,5/menit | 0 |
Pengecualian – DML | 0 | 0 | 25,5/menit |
Perhatikan durasi dan jumlah pengecualian akan sangat bergantung pada spesifikasi server Anda dan apa lagi yang terjadi di lingkungan Anda. Perhatikan juga bahwa, meskipun tidak ada pengecualian untuk tes transfer skema saat menggunakan SQLQueryStress, Anda mungkin mendapatkan batas waktu yang lebih ketat tergantung pada aplikasi yang digunakan. Dan itu jauh lebih lambat rata-rata, karena pemblokiran menumpuk jauh lebih agresif. Tidak ada yang pernah menginginkan pengecualian, tetapi ketika ada kompromi seperti ini, Anda mungkin lebih memilih beberapa pengecualian di sana-sini (tergantung pada frekuensi operasi penyegaran) daripada semua orang yang menunggu lebih lama sepanjang waktu.
Pengalihan Partisi vs. Ganti Nama/Transfer Skema untuk Menyegarkan Tabel SQL Server
Pergantian partisi memungkinkan Anda untuk memilih bagian mana dari proses Anda yang menanggung biaya konkurensi. Anda dapat memberikan preferensi pada proses peralihan, sehingga data lebih andal segar, tetapi ini berarti beberapa kueri Anda akan gagal. Sebaliknya, Anda dapat memprioritaskan kueri, dengan mengorbankan proses penyegaran yang lebih lambat (dan kegagalan sesekali di sana). Dorongan utama adalah pengalihan partisi SQL Server adalah metode yang unggul untuk menyegarkan tabel SQL Server dibandingkan dengan teknik transfer rename/skema sebelumnya di hampir semua titik, dan Anda dapat menggunakan logika coba lagi yang lebih kuat atau bereksperimen dengan toleransi durasi untuk mendarat di sweet spot untuk beban kerja Anda.