Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Menjalankan kueri besar di latar belakang MS SQL

Dari sudut pandang saya, server Anda memiliki masalah kinerja yang serius. Bahkan jika kita berasumsi bahwa tidak ada catatan dalam kueri

select some_col with (nolock) where id_col between 57000000 and 57001000

ada di memori, tidak perlu 21 detik untuk membaca beberapa halaman secara berurutan dari disk (indeks berkerumun Anda di id_col tidak boleh terfragmentasi jika itu adalah identitas otomatis dan Anda tidak melakukan sesuatu yang bodoh seperti menambahkan "desc" ke definisi indeks).

Tetapi jika Anda tidak dapat/tidak akan memperbaikinya, saran saya adalah membuat pembaruan dalam paket kecil seperti 100-1000 catatan sekaligus (tergantung pada berapa banyak waktu yang digunakan fungsi pencarian). Satu pembaruan/transaksi tidak boleh lebih dari 30 detik.

Anda melihat setiap pembaruan menyimpan kunci eksklusif pada semua catatan yang dimodifikasi hingga transaksi selesai. Jika Anda tidak menggunakan transaksi eksplisit, setiap pernyataan dieksekusi dalam satu konteks transaksi otomatis, sehingga kunci dilepaskan saat pernyataan pembaruan selesai.

Tetapi Anda masih bisa mengalami kebuntuan seperti itu, tergantung pada apa yang dilakukan proses lain. Jika mereka juga memodifikasi lebih dari satu record pada satu waktu, atau bahkan jika mereka mengumpulkan dan menahan kunci baca pada beberapa baris, Anda bisa mendapatkan kebuntuan.

Untuk menghindari kebuntuan, pernyataan pembaruan Anda perlu mengunci semua catatan yang akan diubahnya sekaligus. Cara melakukannya adalah dengan menempatkan pernyataan pembaruan tunggal (dengan hanya beberapa baris yang dibatasi oleh id_col) dalam transaksi serial seperti

IF @@TRANCOUNT > 0
  -- Error: You are in a transaction context already

SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

-- Insert Loop here to work "x" through the id range
  BEGIN TRANSACTION
    UPDATE SOMETABLE
      SET [some_col] = dbo.ufn_SomeFunction(CONVERT(NVARCHAR(500), another_column))
      WHERE [some_col] = 243 AND id_col BETWEEN x AND x+500 -- or whatever keeps the update in the small timerange
  COMMIT
-- Next loop

-- Get all new records while you where running the loop. If these are too many you may have to paginate this also:
BEGIN TRANSACTION
  UPDATE SOMETABLE
    SET [some_col] = dbo.ufn_SomeFunction(CONVERT(NVARCHAR(500), another_column))
    WHERE [some_col] = 243 AND id_col >= x
COMMIT

Untuk setiap pembaruan, ini akan mengambil pembaruan/kunci rentang kunci eksklusif pada catatan yang diberikan (tetapi hanya mereka, karena Anda membatasi pembaruan melalui kunci indeks berkerumun). Ini akan menunggu pembaruan lainnya pada catatan yang sama selesai, kemudian menguncinya (menyebabkan pemblokiran untuk semua transaksi lain, tetapi masih hanya untuk catatan yang diberikan), kemudian memperbarui catatan dan melepaskan kunci.

Pernyataan tambahan terakhir adalah penting, karena akan mengambil kunci rentang kunci hingga "tak terhingga" dan dengan demikian mencegah penyisipan yang merata di akhir rentang saat pernyataan pembaruan berjalan.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menghapus Profil Email Database (SSMS)

  2. SQL:mengurai nama depan, tengah dan belakang dari bidang nama lengkap

  3. Bagaimana Anda mengatur autocommit dalam sesi SQL Server?

  4. Perbarui Baris di Tujuan SSIS OLEDB

  5. Memperbarui Data Salesforce dengan Kursor SQL Server