Menggunakan SPID dalam DB Tables (bukan Table Variable)

8

Database transaksional digunakan untuk pemesanan barang ...

Vendor kami diminta untuk mengganti #temptable dengan @tablevariables (karena kunci kompilasi yang berat) tetapi sebaliknya mereka diganti dengan tabel aktual yang menambahkan SPID sebagai kolom untuk memastikan prosedur yang tersimpan hanya bekerja pada baris yang berlaku.

Apakah Anda melihat risiko dalam metode operasi ini? Sebelum semua transaksi diisolasi dalam transaksi mereka sendiri ... Saya khawatir kita mungkin akhirnya mengunci tabel ini banyak, tetapi pendapat mereka adalah bahwa SQL menggunakan penguncian tingkat-baris dan ini tidak akan membuat lebih banyak kunci.

SQL Server Versi: 2016 Enterprise - 13.0.5216.0


CREATE TABLE dbo.qryTransactions (
    ID int IDENTITY (0,1) NOT NULL CONSTRAINT pk_qryTransactions PRIMARY KEY CLUSTERED,
    spid int NOT NULL,
    OrderID int,
    ItemID int,
    TimeTransactionStart datetime,
    TimeTransactionEnd datetime,
...other fields
    )

CREATE INDEX idx_qryTransactions_spidID ON qryTransactions (spid, ID) INCLUDE (ItemID, OrderID, TimeTransactionStart, TimeTransactionEnd)
outjet
sumber
1
Tergantung. Berapa banyak sesi yang secara bersamaan menggunakan tabel, seberapa aktif sesi yang dikatakan, berapa banyak catatan yang ada dalam tabel, apakah catatan dalam tabel baru ini dibersihkan atau tetap, dll? 5 sesi, bukan masalah besar. 500 sesi, kemungkinan besar Anda akan mengalami pemblokiran yang tidak akan Anda lihat dengan tabel sementara / variabel lokal untuk setiap sesi.
John Eisbrener
Versi server sql apa yang Anda gunakan?
Anthony Genovese
2016 Enterprise - 13.0.5216.0
outjet
Rekaman per sesi memukul tabel akan 1-50 ... mereka akan dibersihkan, sehingga meja itu sendiri mungkin tidak akan mendapatkan lebih dari 1.000 baris sekaligus ... sesi bersamaan kemungkinan sekitar 50 ....
outjet
1
Jika Anda dipaksa untuk turun jalan ini (silakan coba untuk menghindarinya) Saya akan berpikir serius untuk mempartisi nilai spid, memastikan bahwa eskalasi kunci pada tabel diatur ke AUTO. Maka setidaknya menghapus data spid tertentu dapat dilakukan dalam operasi sakelar dan terpotong.
Jonathan Fite

Jawaban:

5

Sedikit lebih bertele-tele daripada yang dapat ditampung dalam blok komentar ... dan ingin menyoroti komentar OP yang dibuat dalam menanggapi jawaban Ray:

  • induk proc (Common_InsertOrders_1) membuat tabel temp
  • child proc (InsertOrders) menanyakan tabel temp
  • kunci kompilasi sedang dilihat untuk proc anak (InsertOrders)

Berangkat sedikit menyinggung sebentar ... tentang apa yang akan terjadi dengan skenario ini adalah Sybase ASE ...

  • setiap tabel temp mendapatkan id objek unik (tentu saja, id objek dapat digunakan kembali di beberapa titik tapi ini jarang terjadi, dan tentu saja tidak akan terjadi untuk sesi bersamaan)
  • Sybase ASE biasanya akan memaksa kompilasi ulang pada setiap eksekusi proc anak karena perubahan id objek untuk tabel temp
  • Sybase ASE juga akan memaksa kompilasi ulang proc anak jika melihat bahwa struktur tabel temp telah berubah (misalnya, jumlah kolom yang berbeda, nama kolom yang berbeda / tipe data / nullability) antara permintaan proc yang disimpan
  • versi Sybase ASE yang lebih baru memiliki konfigurasi yang (secara efektif) memberi tahu kompiler untuk mengabaikan perubahan pada id objek tabel temp sehingga menghilangkan kompilasi ulang proc anak (CATATAN: kompilasi ulang akan tetap terjadi jika struktur tabel berubah)

Kembali ke masalah OP (kompilasi kunci pada proc anak) ...

  • apakah ada kemungkinan bahwa beberapa sisa dari perilaku Sybase ASE masih bisa berada di SQL Server (sejak saat kedua produk kacang polong di pod)?
  • apakah ada konfigurasi SQL Server yang dapat mengurangi (menghilangkan?) kompilasi dari proc anak (jika karena perubahan id objek)?
  • dapatkah OP memverifikasi bahwa proc induk membuat tabel temp dengan struktur / DDL yang sama persis setiap kali?

Adapun gagasan menggunakan tabel permanen tunggal dengan @@ SPID untuk membedakan baris antara sesi ... pernah ada, melihat bahwa ... yuck ; masalah berulang:

  • bagaimana / kapan harus membersihkan baris yatim
  • penggunaan kembali @@ SPID oleh mesin basis data dapat menyebabkan masalah akurasi data jika ada data yatim (atau selama pembersihan data yatim, misalnya, hapus di mana @@ SPID = 10 tetapi ada sesi baru / saat ini / aktif dengan @ @ SPID = 10 => pembersihan menghapus terlalu banyak data)
  • potensi eskalasi kunci dari kunci baris ke kunci halaman / tabel
  • jika tabel memiliki indeks, maka berpotensi (b) mengunci saat memperbarui indeks
  • tergantung pada basis data mana tabel berada Anda bisa melihat lebih banyak aktivitas untuk menulis ke perangkat log (di Sybase ASE dimungkinkan untuk, secara efektif, menonaktifkan login di tempdb)
  • bahkan level kunci (eksklusif) kunci dapat memblokir sesi lain (tergantung pada tingkat isolasi dan apakah sesi dapat memindai-melewati / melewati kata kunci eksklusif)

Saya ingin kembali dan (kembali) menyelidiki masalah root (kunci kompilasi pada proc anak) dan melihat apakah ada cara untuk mengurangi (menghilangkan?) Kata kunci kompilasi. [Sayangnya pengetahuan SQL Server saya tentang masalah ini adalah ... NULL ... jadi akan tertarik pada masukan dari beberapa ahli kompiler SQL Server.]

markp-fuso
sumber
1
Saya setuju, saya pikir lebih banyak waktu yang dihabiskan untuk menyelidiki kunci kompilasi. Ini memiliki beberapa poin untuk diselidiki. support.microsoft.com/en-us/help/263889/…
Jonathan Fite
8

Sepertinya saya menggunakan @@SPIDyang meminta masalah.

ID sesi sering digunakan kembali; segera setelah koneksi pengguna keluar, ID sesi itu tersedia untuk digunakan lagi, dan kemungkinan akan digunakan oleh sesi berikutnya yang mencoba untuk terhubung.

Untuk membuatnya berfungsi setidaknya semi-andal, Anda memerlukan pemicu masuk yang membersihkan baris sebelumnya dari tabel dengan yang sama @@SPID. Jika Anda melakukannya, Anda cenderung melihat banyak penguncian di atas meja menggunakan @@SPIDkolom.

SQL Server memang menggunakan penguncian baris, tetapi juga menggunakan penguncian halaman, dan penguncian tabel. Tentu saja, Anda mungkin dapat mengurangi itu melalui pengindeksan yang baik, tetapi ini masih terlihat seperti anti-pola bagi saya.

Jika prosedur tersimpan adalah satu - satunya metode yang digunakan untuk mengakses tabel yang terpengaruh, Anda dapat menyelidiki dengan menggunakan kunci aplikasi, melalui sp_getapplockuntuk pada dasarnya membuat serial akses ke bagian yang relevan. Documents untuk sp_getapplock ada di sini . Erik Darling memiliki pos yang menarik tentang hal itu di sini .

Max Vernon
sumber
4

Ya, saya melihat risiko. Adalah naif untuk mengandalkan SQL menggunakan Penguncian Baris. Misalnya, saya cukup yakin memasukkan dan menghapus akan menggunakan kunci halaman setidaknya. SQL Engine memilih jenis kunci berdasarkan beberapa faktor dan tidak satu pun dari faktor tersebut termasuk "pendapat mereka". Solusi selimut seperti mengubah variabel tabel temp ke tabel umumnya juga merupakan ide yang buruk. Variabel tabel sangat berguna dalam beberapa situasi tetapi mereka memang memiliki keterbatasan dan masalah kinerja. Saya lebih suka tabel temp di sebagian besar keadaan. Terutama ketika meja akan menampung lebih dari beberapa lusin baris. Saya akan meminta vendor untuk menjelaskan mengapa sistem mengalami "kunci kompilasi berat" dan bagaimana itu menurunkan kinerja. Ingat, kapan pun Anda melihatnya, Anda akan menemukan "kunci berat". Itu tidak berarti bahwa kunci adalah masalah. Maks ' Komentar tentang @@ SPID juga penting. Selain itu, model transaksi dan pemrosesan kesalahan bisa menjadi masalah besar. Jika sistem Anda mengalami kebuntuan atau menginput masalah kualitas data maka pemrosesan kesalahan standar dapat mengakibatkan sesi dihentikan tanpa tabel qryTransactions sedang diatur ulang dengan benar. IMO pendekatan solusi yang salah dengan masalah aslinya.

sinar
sumber
Terima kasih atas jawabannya - untuk poin Anda: jejak kami menunjukkan LCK yang berat menunggu kunci kompilasi pada prosedur yang tersimpan InsertOrders. Ada prosedur induk Common_InsertOrders_1 yang menyatakan tabel temp #qryTransactions dan kemudian prosedur bersarang InsertOrders_2 menanyakan Tabel Temp. Selain itu, kami mengetahui bahwa ada juga kompilasi ulang yang sering dilakukan karena setelah 6 modifikasi ke tabel sementara yang kosong, setiap prosedur tersimpan yang merujuk bahwa tabel sementara perlu dikompilasi ulang
outjet
Ada banyak alasan prosedur atau pernyataan akan dikompilasi ulang. MarkP menyebutkan beberapa dari mereka yang berlaku di SyBase dan saya yakin SQL Server serupa. Jumlah baris tabel temp adalah contoh yang baik dan kompilasi ulang tidak selalu merupakan hal yang buruk. Tabel statistik secara substansial dapat mengubah Rencana Kueri yang optimal dan kompilasi ulang diperlukan untuk menentukan itu. Tapi saya ingin mengulang kembali. Akan selalu ada kunci atas dan itu tidak berarti kunci adalah masalah. Kecuali Anda melihat bukti lain dari masalah kinerja maka jangan khawatir tentang hal itu.
Ray