Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Mengganti Kursor SQL dengan Alternatif untuk Menghindari Masalah Kinerja

Dalam artikel ini, kita akan melihat beberapa alternatif untuk menggunakan kursor SQL yang dapat membantu menghindari masalah kinerja yang disebabkan oleh penggunaan kursor.

Sebelum membahas alternatifnya, mari kita tinjau kembali konsep umum kursor SQL.

Ikhtisar Singkat Kursor SQL

Kursor SQL terutama digunakan di mana operasi berbasis set tidak berlaku dan Anda diminta untuk mengakses data dan melakukan operasi satu baris pada satu waktu daripada menerapkan operasi berbasis set tunggal ke seluruh objek (seperti tabel atau sekumpulan tabel).

Definisi Sederhana

Kursor SQL menyediakan akses ke data satu baris pada satu waktu, sehingga memberi Anda kontrol baris demi baris langsung atas kumpulan hasil.

Definisi Microsoft

Menurut dokumentasi Microsoft, pernyataan Microsoft SQL Server menghasilkan kumpulan hasil yang lengkap, tetapi ada kalanya yang terbaik adalah memprosesnya satu baris pada satu waktu – yang dapat dilakukan dengan membuka kursor pada kumpulan hasil.

Proses 5 Langkah Menggunakan Kursor

Proses penggunaan kursor SQL secara umum dapat digambarkan sebagai berikut:

  1. Deklarasikan Kursor
  2. Buka Kursor
  3. Ambil baris
  4. Tutup Kursor
  5. Alokasikan Kursor

Catatan Penting

Harap diingat bahwa, menurut Vaidehi Pandere, kursor adalah penunjuk yang menempati memori sistem Anda – yang seharusnya dicadangkan untuk proses penting lainnya. Itulah mengapa melintasi hasil besar yang ditetapkan dengan menggunakan kursor biasanya bukan ide terbaik – kecuali jika ada alasan yang sah untuk melakukannya.

Untuk informasi lebih rinci tentang ini, silakan merujuk ke artikel saya Cara menggunakan Kursor SQL untuk Keperluan Khusus.

Contoh Kursor SQL

Pertama, kita akan melihat contoh bagaimana kursor SQL dapat digunakan untuk mengganti nama objek database satu per satu.

Untuk membuat kursor SQL yang kita butuhkan, mari kita siapkan database sampel sehingga kita dapat menjalankan skrip kita terhadapnya.

Menyiapkan Contoh Basis Data (UniversityV3)

Jalankan skrip berikut untuk membuat dan mengisi database sampel UniversityV3 dengan dua tabel:

-- (1) Create UniversityV3 sample database

CREATE DATABASE UniversityV3;

GO

USE UniversityV3

-- (2) Create Course table

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES T WHERE T.TABLE_NAME='Course') 

DROP TABLE dbo.Course 

CREATE TABLE [dbo].[Course] (

    [CourseId] INT           IDENTITY (1, 1) NOT NULL,

    [Name]     VARCHAR (30)  NOT NULL,

    [Detail]   VARCHAR (200) NULL,

    CONSTRAINT [PK_Course] PRIMARY KEY CLUSTERED ([CourseId] ASC)

);

-- (3) Create Student table

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES T WHERE T.TABLE_NAME='Student') 

DROP TABLE dbo.Student 

CREATE TABLE [dbo].[Student] (

    [StudentId] INT           IDENTITY (1, 1) NOT NULL,

    [Name]      VARCHAR (30)  NULL,

    [Course]    VARCHAR (30)  NULL,

    [Marks]     INT           NULL,

    [ExamDate]  DATETIME2 (7) NULL,

    CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED ([StudentId] ASC)

);

-- (4) Populate Course table

SET IDENTITY_INSERT [dbo].[Course] ON

INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) VALUES (1, N'DevOps for Databases', N'This is about DevOps for Databases')

INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) VALUES (2, N'Power BI Fundamentals', N'This is about Power BI Fundamentals')

INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) VALUES (3, N'T-SQL Programming', N'About T-SQL Programming')

INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) VALUES (4, N'Tabular Data Modeling', N'This is about Tabular Data Modeling')

INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) VALUES (5, N'Analysis Services Fundamentals', N'This is about Analysis Services Fundamentals')

SET IDENTITY_INSERT [dbo].[Course] OFF



-- (5) Populate Student table

SET IDENTITY_INSERT [dbo].[Student] ON

INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks], [ExamDate]) VALUES (1, N'Asif', N'Database Management System', 80, N'2016-01-01 00:00:00')

INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks], [ExamDate]) VALUES (2, N'Peter', N'Database Management System', 85, N'2016-01-01 00:00:00')

INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks], [ExamDate]) VALUES (3, N'Sam', N'Database Management System', 85, N'2016-01-01 00:00:00')

INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks], [ExamDate]) VALUES (4, N'Adil', N'Database Management System', 85, N'2016-01-01 00:00:00')

INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks], [ExamDate]) VALUES (5, N'Naveed', N'Database Management System', 90, N'2016-01-01 00:00:00')

SET IDENTITY_INSERT [dbo].[Student] OFF

Buat Kursor SQL untuk Mengganti Nama Tabel (_Backup)

Sekarang pertimbangkan untuk memenuhi spesifikasi berikut dengan menggunakan kursor:

  1. Kita perlu menambahkan '_Backup' ke nama semua tabel yang ada di database
  2. Tabel yang sudah memiliki '_Backup' di namanya tidak boleh diganti namanya

Mari kita buat kursor SQL untuk mengganti nama semua tabel dalam database sampel dengan menambahkan ‘_Backup’ ke setiap nama tabel sambil juga memastikan bahwa tabel yang berisi ‘_Backup’ dalam namanya tidak akan diganti namanya lagi dengan menjalankan kode berikut:

-- Declaring the Student cursor to rename all tables by adding ‘_backup’ to their names and also making sure that all tables that are already named correctly will be skipped:

USE UniversityV3
GO

DECLARE @TableName VARCHAR(50) -- Existing table name
       ,@NewTableName VARCHAR(50) -- New table name

DECLARE Student_Cursor CURSOR FOR SELECT T.TABLE_NAME FROM INFORMATION_SCHEMA.TABLES T;

OPEN Student_Cursor

FETCH NEXT FROM Student_Cursor INTO @TableName

WHILE @@FETCH_STATUS = 0

BEGIN

IF RIGHT(@TableName,6)<>'Backup' -- If Backup table does not exist then rename the table

BEGIN

SET @[email protected]+'_Backup' -- Add _Backup to the table’s current name

EXEC sp_rename @TableName,@NewTableName -- Rename table as OLD table

END

ELSE

PRINT 'Backup table name already exists: '[email protected]

FETCH NEXT FROM Student_Cursor -- Get next row data into cursor and store it in variables

INTO @TableName

END

CLOSE Student_Cursor -- Close cursor locks on the rows

DEALLOCATE Student_Cursor -- Release cursor reference

Jalankan Skrip Penggantian Nama dan Lihat Hasil

Sekarang, Tekan F5 di SSMS (SQL Server Management Studio) untuk menjalankan skrip dan lihat hasilnya:

Menyegarkan nama tabel di penjelajah objek SSMS dengan jelas menunjukkan bahwa kami telah berhasil mengubahnya seperti yang ditentukan.

Mari kita jalankan kembali script tersebut dengan menekan F5 lagi dan lihat hasilnya:

Membuat Kursor SQL untuk Menyetel Ulang _Penamaan Cadangan

Kita juga perlu membuat skrip yang menggunakan kursor SQL untuk mengembalikan nama tabel yang baru saja kita ubah kembali ke yang awal – kita akan melakukannya dengan menghapus ‘_Backup’ dari namanya.

Script di bawah ini akan membiarkan kita melakukan hal itu :

-- Declare the Student cursor to reset tables names _backup to their original forms by removing ‘_backup’

USE UniversityV3

GO

DECLARE @TableName VARCHAR(50) -- Existing table name
       ,@NewTableName VARCHAR(50) -- New table name

DECLARE Student_Cursor CURSOR FOR SELECT T.TABLE_NAME FROM INFORMATION_SCHEMA.TABLES T;

OPEN Student_Cursor

FETCH NEXT FROM Student_Cursor INTO @TableName

WHILE @@FETCH_STATUS = 0

BEGIN

IF RIGHT(@TableName,6)='Backup' -- If Backup table name exists then reset (rename) it

BEGIN

SET @NewTableName=SUBSTRING(@TableName,1,LEN(@TableName)-7) -- Remove _Backup from the table name

EXEC sp_rename @TableName,@NewTableName -- Rename table 

END

ELSE

PRINT 'Backup table name already reset: '[email protected]

FETCH NEXT FROM Student_Cursor – Get the data of the next row into cursor and store it in variables

INTO @TableName

END

CLOSE Student_Cursor -- Close cursor locks on the rows

DEALLOCATE Student_Cursor -- Release cursor reference

Jalankan Skrip Reset dan Lihat Hasil

Menjalankan skrip menunjukkan bahwa nama tabel telah berhasil diatur ulang:

Ini adalah contoh dari beberapa skenario di mana sulit untuk menghindari penggunaan kursor SQL karena sifat persyaratannya. Namun, masih mungkin untuk menemukan pendekatan alternatif.

Alternatif Kursor SQL

Ada dua alternatif yang paling umum untuk kursor SQL, jadi mari kita lihat masing-masing secara mendetail.

Alternatif 1:Variabel Tabel

Salah satu alternatif ini adalah variabel tabel.

Variabel tabel, seperti tabel, dapat menyimpan banyak hasil – tetapi dengan beberapa batasan. Menurut dokumentasi Microsoft, variabel tabel adalah tipe data khusus yang digunakan untuk menyimpan kumpulan hasil untuk diproses di lain waktu.

Namun, perlu diingat bahwa variabel tabel paling baik digunakan dengan kumpulan data kecil.

Variabel tabel bisa sangat efisien untuk kueri skala kecil karena berfungsi seperti variabel lokal dan dibersihkan secara otomatis setelah keluar dari cakupan.

Strategi Variabel Tabel:

Kami akan menggunakan variabel tabel alih-alih kursor SQL untuk mengganti nama semua tabel dari database dengan mengikuti langkah-langkah berikut:

  1. Deklarasikan variabel tabel
  2. Simpan nama tabel dan id dalam variabel tabel yang kita deklarasikan
  3. Setel penghitung ke 1 dan dapatkan jumlah total record dari variabel tabel
  4. Gunakan perulangan 'sementara' selama penghitung kurang dari atau sama dengan jumlah total record
  5. Di dalam loop 'sementara', kami akan mengganti nama tabel satu per satu selama tabel tersebut belum diganti namanya dan meningkatkan penghitung untuk setiap tabel

Kode Variabel Tabel:

Jalankan skrip SQL berikut yang membuat dan menggunakan variabel tabel untuk mengganti nama tabel:

-- Declare Student Table Variable to rename all tables by adding ‘_backup’ t their name and also making sure that already renamed tables are skipped

USE UniversityV3

GO

DECLARE @TableName VARCHAR(50) -- Existing table name
       ,@NewTableName VARCHAR(50) -- New table name

DECLARE @StudentTableVar TABLE -- Declaring a table variable to store tables names
(
TableId INT,

TableName VARCHAR(40))

INSERT INTO @StudentTableVar -- insert tables names into the table variable 

SELECT ROW_NUMBER() OVER(ORDER BY T.TABLE_NAME),T.TABLE_NAME FROM INFORMATION_SCHEMA.TABLES T

DECLARE @TotalRows INT=(SELECT COUNT(*) FROM @StudentTableVar),@i INT=1 -- Get total rows and set counter to 1

WHILE @i<[email protected] -- begin as long as i (counter) is less than or equal to the total number of records

BEGIN -- ‘While’ loop begins here

SELECT @TableName=TableName from @StudentTableVar WHERE [email protected]

IF RIGHT(@TableName,6)<>'Backup' -- If a Backup table does not exist, then rename the table

BEGIN

SET @[email protected]+'_Backup' -- Add _Backup to the table’s current name

EXEC sp_rename @TableName,@NewTableName -- Rename the table as OLD table

END

ELSE

PRINT 'Backup table name already exists: '[email protected]

SET @[email protected]+1

END -- 'While' loop ends here

Jalankan Script dan Lihat hasilnya

Sekarang, mari kita jalankan skrip dan periksa hasilnya:

Alternatif 2:Tabel Sementara

Kami juga dapat menggunakan tabel sementara alih-alih kursor SQL untuk mengulangi hasil yang ditetapkan satu baris pada satu waktu.

Tabel sementara telah digunakan untuk waktu yang lama dan menyediakan cara terbaik untuk mengganti kursor untuk kumpulan data besar.

Sama seperti variabel tabel, tabel sementara dapat menampung kumpulan hasil sehingga kita dapat melakukan operasi yang diperlukan dengan memprosesnya dengan algoritme iterasi seperti loop 'sementara'.

Strategi Tabel Sementara:

Kami akan menggunakan tabel sementara untuk mengganti nama semua tabel dalam database sampel dengan mengikuti langkah-langkah berikut:

  1. Deklarasikan tabel sementara
  2. Simpan nama dan id tabel di tabel sementara yang baru saja kita deklarasikan
  3. Setel penghitung ke 1 dan dapatkan jumlah total catatan dari tabel sementara
  4. Gunakan perulangan 'sementara' selama penghitung kurang dari atau sama dengan jumlah total record
  5. Dalam loop 'sementara', ganti nama tabel satu per satu asalkan belum diganti namanya dan tambah penghitung untuk setiap tabel

Setel ulang tabel

Kita perlu mengatur ulang nama tabel ke bentuk awalnya dengan menghapus '_Backup' dari akhir namanya, jadi silakan jalankan kembali skrip reset yang telah kita tulis dan gunakan di atas sehingga kita dapat menerapkan metode lain untuk mengganti nama tabel.

Kode Tabel Sementara:

Jalankan skrip SQL berikut untuk membuat dan menggunakan tabel sementara untuk mengganti nama semua tabel di database kami:

-- Declare the Student Temporary Table to rename all tables by adding ‘_backup’ to their names while also making sure that already renamed tables are skipped

USE UniversityV3

GO

DECLARE @TableName VARCHAR(50) -- Existing table name
       ,@NewTableName VARCHAR(50) -- New table name

CREATE TABLE #Student -- Declaring a temporary table

(
TableId INT,
TableName VARCHAR(40)
)

INSERT INTO #Student -- insert tables names into the temporary table

SELECT ROW_NUMBER() OVER(ORDER BY T.TABLE_NAME),T.TABLE_NAME FROM INFORMATION_SCHEMA.TABLES T

DECLARE @TotalRows INT=(SELECT COUNT(*) FROM #Student),@i INT=1 -- Get the total amount of rows and set the counter to 1

WHILE @i<[email protected] -- begin as long as i (counter) is less than or equal to the total number of records

BEGIN -- ‘While’ loop begins here

SELECT @TableName=TableName from #Student WHERE [email protected]

IF RIGHT(@TableName,6)<>'Backup' -- If a Backup table does not exist, then rename the table

BEGIN

SET @[email protected]+'_Backup' -- Add ‘_Backup’ to the table’s current name

EXEC sp_rename @TableName,@NewTableName -- Rename the table as OLD table

END

ELSE

PRINT 'Backup table name already exists: '[email protected]

SET @[email protected]+1

END -- While loop ends here

DROP TABLE #Student

Jalankan Script dan Periksa Outputnya

Sekarang, mari kita jalankan skrip untuk melihat hasilnya:

Hal yang Dapat Dilakukan

Sekarang Anda sudah familiar dengan alternatif kursor SQL – seperti menggunakan variabel tabel dan tabel sementara – silakan coba lakukan hal-hal berikut untuk membiasakan diri menerapkan pengetahuan ini dalam praktik:

  1. Membuat dan mengganti nama indeks semua tabel dalam database sampel – pertama melalui Kursor, lalu dengan menggunakan metode alternatif (variabel tabel dan tabel sementara)
  2. Kembalikan nama tabel dari artikel ini ke nama awalnya menggunakan metode alternatif (tabel sementara dan variabel tabel)
  3. Anda juga dapat merujuk ke contoh pertama di artikel saya Cara menggunakan Kursor SQL untuk Keperluan Khusus dan mencoba mengisi tabel dengan banyak baris dan mengukur statistik dan waktu kueri untuk membandingkan metode kursor dasar dengan alternatif

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jenis-jenis SQL JOIN

  2. Cara Menghitung Perbedaan Antara Dua Datetime di T-SQL

  3. Kompleksitas NULL – Bagian 1

  4. Lebih banyak peningkatan showplan? Ya silahkan!

  5. Penyembunyian Data Dinamis Berbasis Proksi di FieldShield