Ditambahkan 7/11 Masalahnya adalah kebuntuan terjadi karena pemindaian indeks selama Gabung BERGABUNG. Dalam hal ini transaksi mencoba untuk mendapatkan kunci S pada seluruh indeks di tabel induk FK, tetapi sebelumnya transaksi lain menempatkan kunci X pada nilai kunci indeks.
Mari saya mulai dengan contoh kecil (TSQL2012 DB dari 70-461 cource digunakan):
CREATE TABLE [Sales].[Orders](
[orderid] [int] IDENTITY(1,1) NOT NULL,
[custid] [int] NULL,
[empid] [int] NOT NULL,
[shipperid] [int] NOT NULL,
... )
Kolom [custid], [empid], [shipperid]
adalah parameter terkait untuk [Sales].[Customers], [HR].[Employees], [Sales].[Shippers]
sesuai. Dalam setiap kasus kami memiliki indeks berkerumun pada kolom yang dirujuk dalam tabel parrent.
ALTER TABLE [Sales].[Orders] WITH CHECK ADD CONSTRAINT [FK_Orders_Customers] FOREIGN KEY([custid]) REFERENCES [Sales].[Customers] ([custid])
ALTER TABLE [Sales].[Orders] WITH CHECK ADD CONSTRAINT [FK_Orders_Employees] FOREIGN KEY([empid]) REFERENCES [HR].[Employees] ([empid])
ALTER TABLE [Sales].[Orders] WITH CHECK ADD CONSTRAINT [FK_Orders_Shippers] FOREIGN KEY([shipperid])REFERENCES [Sales].[Shippers] ([shipperid])
Saya mencoba ke INSERT [Sales].[Orders] SELECT ... FROM
meja lain yang disebut [Sales].[OrdersCache]
yang memiliki struktur yang sama dengan [Sales].[Orders]
kecuali kunci asing. Hal lain yang mungkin penting untuk menyebutkan tabel [Sales].[OrdersCache]
adalah indeks berkerumun.
CREATE CLUSTERED INDEX idx_c_OrdersCache ON Sales.OrdersCache ( custid, empid )
Seperti yang diharapkan ketika saya mencoba untuk memasukkan data volume rendah LOOP JOIN berfungsi dengan baik membuat indeks pencarian pada kunci asing.
Dengan volume data yang tinggi, MERGE BERGABUNG digunakan oleh pengoptimal query sebagai cara paling efisien untuk mempertahankan kunci foregn dalam kueri.
Dan tidak ada hubungannya dengan itu kecuali menggunakan OPTION (LOOP JOIN) dalam kasus kami dengan kunci asing atau INNER LOOP JOIN dalam kasus JOIN eksplisit.
Di bawah ini adalah permintaan yang saya coba jalankan di lingkungan saya:
INSERT Sales.Orders (
custid, empid, shipperid, ... )
SELECT custid, empid, 2, ...
FROM Sales.OrdersCache
Melihat rencana itu, kita dapat melihat bahwa ketiga kunci foreing divalidasi dengan MERGE JOIN. Itu bukan cara yang tepat bagi saya karena menggunakan INDEX SCAN dengan penguncian seluruh indeks.
Menggunakan OPTION (LOOP JOIN) tidak cocok karena biayanya hampir 15% lebih banyak daripada MERGE JOIN (saya pikir regresi akan lebih besar dengan volume data yang tumbuh).
Dalam pernyataan SELECT Anda dapat melihat nilai tunggal untuk shipperid
atribut untuk seluruh set yang dimasukkan. Menurut pendapat saya harus ada cara untuk membuat fase validasi untuk set yang dimasukkan lebih cepat setidaknya untuk atribut yang tidak dapat diubah. Sesuatu seperti:
- buat LOOP BERGABUNG, GABUNG GABUNG, HASH GABUNG jika kami memiliki subset yang tidak ditentukan untuk validasi GABUNG
- jika hanya ada satu nilai eksplisit dari kolom yang divalidasi, kami membuat validasi hanya sekali (INDEKS SEEK).
Apakah ada pola umum untuk melewati situasi di atas menggunakan struktur kode, objek DDL tambahan, dll?
Ditambahkan 20/07. Larutan. Pengoptimal Permintaan sudah membuat optimasi validasi 'kunci tunggal - kunci asing' dengan menggunakan MERGE BERGABUNG. Dan hanya dibuat untuk tabel Sales.Shippers, meninggalkan LOOP BERGABUNG untuk bergabung dalam kueri pada saat yang sama. Karena saya memiliki beberapa baris dalam tabel induk Query Optimizer menggunakan algoritme gabungan Gabung-gabungkan dan bandingkan setiap baris di tabel dalam dengan tabel induk hanya sekali. Jadi itulah jawaban pada pertanyaan saya jika ada mekanisme tertentu untuk secara efektif memproses nilai-nilai tunggal dalam satu set selama validasi kunci tunggal. Itu bukan keputusan yang sempurna tapi itulah cara SQL Server mengoptimalkan kasus ini.
Investigasi yang memengaruhi kinerja mengungkapkan bahwa dalam kasus saya, pernyataan penyatuan MERGE JOIN dan LOOP JOIN menjadi kira-kira sama dengan 750 baris yang disisipkan secara simultan dengan superioritas MERGE JOIN berikut (dalam sumber daya waktu CPU). Jadi menggunakan OPTION (LOOP JOIN) adalah solusi yang tepat untuk proses bisnis saya.