SQL Server NOLOCK dan bergabung

153

Latar belakang: Saya memiliki permintaan kinerja kritis yang ingin saya jalankan dan saya tidak peduli dengan pembacaan yang kotor.

Pertanyaanku adalah; Jika saya menggunakan gabungan, apakah saya harus menentukan petunjuk NOLOCK juga?

Misalnya; adalah:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b WITH (NOLOCK) ON a.ID = b.ID

Setara dengan:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b ON a.ID = b.ID

Atau apakah saya perlu menentukan (NOLOCK)petunjuk pada join untuk memastikan saya tidak mengunci tabel yang digabungkan?

DanP
sumber

Jawaban:

166

Saya tidak akan membahas READ UNCOMMITTEDargumen, hanya pertanyaan awal Anda.

Ya, Anda perlu WITH(NOLOCK)pada setiap tabel yang bergabung. Tidak, pertanyaan Anda tidak sama.

Coba latihan ini. Mulai transaksi dan masukkan baris ke table1 dan table2. Jangan melakukan atau mengembalikan transaksi. Pada titik ini permintaan pertama Anda akan kembali dengan sukses dan menyertakan baris yang tidak dikomit; permintaan kedua Anda tidak akan kembali karena table2 tidak memiliki WITH(NOLOCK)petunjuk tentang itu.

codeConcussion
sumber
18

Saya cukup yakin bahwa Anda perlu menentukan NOLOCKuntuk masing-masing JOINdi kueri. Tetapi pengalaman saya terbatas pada SQL Server 2005.

Ketika saya mencari MSDN hanya untuk konfirmasi, saya tidak dapat menemukan sesuatu yang pasti. Pernyataan di bawah ini sepertinya membuat saya berpikir, bahwa untuk tahun 2008, kedua pernyataan Anda di atas adalah sama meskipun untuk tahun 2005 tidak demikian:

[SQL Server 2008 R2]

Semua petunjuk kunci disebarkan ke semua tabel dan tampilan yang diakses oleh rencana kueri , termasuk tabel dan tampilan yang dirujuk dalam tampilan. Juga, SQL Server melakukan pemeriksaan konsistensi kunci yang sesuai.

[SQL Server 2005]

Dalam SQL Server 2005, semua petunjuk kunci disebarkan ke semua tabel dan tampilan yang direferensikan dalam tampilan. Juga, SQL Server melakukan pemeriksaan konsistensi kunci yang sesuai.

Selain itu, tunjuk catatan - dan ini berlaku untuk 2005 dan 2008:

Petunjuk tabel diabaikan jika tabel tidak diakses oleh rencana kueri. Ini mungkin disebabkan oleh pengoptimal yang memilih untuk tidak mengakses tabel sama sekali, atau karena tampilan yang diindeks diakses sebagai gantinya. Dalam kasus terakhir, mengakses tampilan yang diindeks dapat dicegah dengan menggunakan OPTION (EXPAND VIEWS)petunjuk kueri.

Jagmag
sumber
@In Sane: Menarik ... terima kasih untuk itu ... Saya berasumsi bahwa saya tidak melakukan kesalahan dengan memasukkannya ke dalam GABUNGAN, bahkan jika itu tidak sepenuhnya diperlukan? Dokumentasi tentang NOLOCK sangat jarang seperti yang Anda sebutkan; Saya kesulitan menemukan sesuatu yang konklusif.
DanP
2
@InSane: Dari mana Anda mendapatkan info ini? Tampaknya bertentangan dengan jawaban yang diterima.
Jay Sullivan
1
@notfed - lihat tautan tautan technet.microsoft.com/en-us/library/ms187373(v=sql.105).aspx - Anda dapat mengubah versi basis data di atas untuk membandingkan artikel yang sama untuk berbagai versi db
Jagmag
2
Teks 2005 berbicara tentang VIEWS. Jadi jika Anda melakukan "from myview with (nolock)" maka dikatakan nolock disebarkan ke semua tabel dan pandangan yang terlibat dalam myview (Anda dapat memiliki 10 bergabung di sana). Tidak yakin apa arti sebenarnya teks 2008 karena menambahkan "diakses oleh rencana kueri" di samping tampilan.
Thierry_S
9

Tidak juga. Anda mengatur level isolasi READ UNCOMMITTEDyang selalu lebih baik daripada memberikan petunjuk kunci individual. Atau, lebih baik lagi, jika Anda peduli tentang detail seperti konsistensi , gunakan isolasi snapshot .

Remus Rusanu
sumber
@Remus: Saya tidak yakin dapat menggunakan READ UNCOMMITTED dalam kasus saya karena saya mengakses koneksi melalui NHibernate untuk melakukan panggilan ADO.NET mentah khusus; dapatkah ini ditentukan secara inline dalam kueri, atau akankah ia mematuhi tingkat transaksi yang ada pada transaksi NHibernate?
DanP
Bungkus panggilan masuk using (TransactionScope scope=new TransactionScope(..., TransactionOptions) {...}dan atur IsolationLevelopsi: msdn.microsoft.com/en-us/library/…
Remus Rusanu
@Remus: Sayangnya, manajemen transaksi dijaga pada tingkat yang jauh lebih tinggi dari ini, jadi itu juga bukan pilihan.
DanP
Saya melihat. Kemudian untuk menjawab pertanyaan Anda: NOLOCK adalah petunjuk tabel , dan karena itu berlaku untuk rowset yang sedang ditambahkan (tabel, tampilan, TVF dll). Jika Anda memiliki beberapa rowset yang digabungkan dalam sebuah kueri, masing-masing akan memerlukan petunjuk NOLOCK sendiri.
Remus Rusanu
2
Tetapi apakah Anda sudah mempertimbangkan isolasi snapshot? ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON;. Hasilnya spektakuler, karena semua bacaan yang dibaca normal berubah menjadi bacaan snapshot, terkunci bebas namun konsisten. Biaya bertambah tempdbbeban: msdn.microsoft.com/en-us/library/ms175492.aspx
Remus Rusanu