Cursor Yapısını Set Tabanlı Insert Yapısına Dönüştürme
Müşterimizle yakın zamanda yaptığımız Kapsamlı Veritabanı Performansı Durum Denetimi sırasında, ekleme işlemleri için Cursor kullanımıyla ilgili, sunucunun genel performansı üzerinde zararlı bir etkisi olan önemli bir sorunla karşılaştık. İmleçler, belirli durumlarda yararlı olmakla birlikte, özellikle büyük sonuç kümeleriyle uğraşırken yavaş ve kaynak yoğun olabilir. Sonuç olarak, performansı iyileştirmek için alternatif yaklaşımları keşfetmek önemlidir. Bu blog gönderisinde, Cursor tabanlı eklemeler konusuna odaklanacağız ve bunların küme tabanlı işlemlere nasıl dönüştürüleceğini göstereceğiz.
Örnek Kurulum
İlk olarak, bir örnek tablo oluşturacağız ve onu bazı verilerle dolduracağız. Aşağıdaki script, üç sütunlu Çalışan adlı bir tablo oluşturur: EmployeeID, FirstName, and LastName.
CREATE TABLE Employee (
EmployeeID INT,
FirstName VARCHAR(50),
LastName VARCHAR(50)
);
GO
INSERT INTO Employee VALUES (1, ‘John’, ‘Doe’);
INSERT INTO Employee VALUES (2, ‘Jane’, ‘Doe’);
INSERT INTO Employee VALUES (3, ‘Bob’, ‘Smith’);
INSERT INTO Employee VALUES (4, ‘Alice’, ‘Jones’);
GO
CREATE TABLE EmployeeCopy (
EmployeeID INT,
FirstName VARCHAR(50),
LastName VARCHAR(50)
);
Ardından, Çalışan tablosunda yinelenen ve her satırda bir ekleme işlemi gerçekleştiren bir Cursor oluşturacağız. Aşağıdaki komut dosyası bunun nasıl yapılacağını gösterir:
Bu Cursor, Çalışan tablosunda yinelenir ve her satır için EmployeeID, FirstName, and LastName sütunlarını alır. Ardından, Çalışan tablosunun bir kopyası olan EmployeeCopy tablosunda bir ekleme işlemi gerçekleştirir. Bu komut dosyası çalıştırılmadan önce EmployeeCopy tablosunun oluşturulması gerektiğini unutmayın.
DECLARE @EmployeeID INT;
DECLARE @FirstName VARCHAR(50);
DECLARE @LastName VARCHAR(50);
DECLARE EmployeeCursor CURSOR FOR
SELECT EmployeeID, FirstName, LastName
FROM Employee;
OPEN EmployeeCursor;
FETCH NEXT FROM EmployeeCursor INTO @EmployeeID, @FirstName, @LastName;
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO EmployeeCopy (EmployeeID, FirstName, LastName)
VALUES (@EmployeeID, @FirstName, @LastName);
FETCH NEXT FROM EmployeeCursor INTO @EmployeeID, @FirstName, @LastName;
END
CLOSE EmployeeCursor;
DEALLOCATE EmployeeCursor;
Şimdi, Cursor tabanlı eklemeyi set tabanlı eklemeye dönüştürelim. Aşağıdaki komut dosyası bunun nasıl yapılacağını gösterir:
INSERT INTO EmployeeCopy (EmployeeID, FirstName, LastName)
SELECT EmployeeID, FirstName, LastName
FROM Employee;
Bu script, Çalışan tablosundan EmployeeID, FirstName, and LastName sütunlarını alan ve bunları EmployeeCopy tablosuna ekleyen bir seçme ifadesi gerçekleştirir. Bu yaklaşım küme tabanlıdır, yani her seferinde bir satır yinelemek yerine sonuç kümesinin tamamı üzerinde aynı anda çalışır.
Son olarak, Cursor tabanlı ekleme ile küme tabanlı eklemenin performansını karşılaştıralım. Her yaklaşımın yürütme süresini ölçmek için aşağıdaki betiği kullanabiliriz:
DECLARE @StartTime DATETIME;
DECLARE @EndTime DATETIME;
DECLARE @Duration INT;
SET @StartTime = GETDATE();
— …
— Cursor-based insert
— …
SET @EndTime = GETDATE();
SET @Duration = DATEDIFF(MILLISECOND, @StartTime, @EndTime);
PRINT ‘Cursor-based insert duration: ‘ + CAST(@Duration AS VARCHAR(10)) + ‘ms’;
SET @StartTime = GETDATE();
— …
— Setbased insert
— …
SET @EndTime = GETDATE();
SET @Duration = DATEDIFF(MILLISECOND, @StartTime, @EndTime);
PRINT ‘Set-based insert duration: ‘ + CAST(@Duration AS VARCHAR(10)) + ‘ms’;
Bu script, Cursor tabanlı eklemenin ve küme tabanlı eklemenin yürütme süresini ölçer ve sonuçları konsola yazdırır. Yürütme süresini ölçmek için Cursor tabanlı ekleme kodunun açıklamasını kaldırmanız gerektiğini unutmayın.
Bu betiği çalıştırdığımızda aşağıdaki çıktıyı alıyoruz:
Cursor-based insert duration: 22ms
Set-based insert duration: 0ms
Gördüğünüz gibi, küme tabanlı ekleme işlemi Cursor tabanlı ekleme işleminden çok daha hızlıdır ve Cursor tabanlı ekleme için 18 ms ile karşılaştırıldığında yalnızca 0 ms sürer. Bunun nedeni, küme tabanlı eklemenin sonuç kümesinin tamamında aynı anda çalışması, Cursor tabanlı eklemenin ise sonuç kümesinde her seferinde bir satır yineleme yapmasıdır; bu, yavaş ve kaynak yoğun olabilir.
Bu blog gönderimizde, SQL Server’da bir imlecin küme tabanlı bir ekleme işlemine nasıl dönüştürüleceğini gösterdik. Örnek bir tablo oluşturduk, onu bazı verilerle doldurduk ve ardından veriler arasında yinelenen ve her satırda bir ekleme işlemi gerçekleştiren bir Cursor oluşturduk. Daha sonra imleci küme tabanlı bir ekleme işlemine dönüştürdük ve iki yaklaşımın performansını karşılaştırdık. Küme tabanlı ekleme işleminin Cursor tabanlı ekleme işleminden çok daha hızlı ve verimli olduğunu bulduk ve SQL Server’da küme tabanlı işlemleri kullanmanın faydalarını vurgulamış olduk.
[vc_row full_width=”stretch_row” css=”.vc_custom_1505794887127{background-color: #2596be !important;}” gradient_animation=”#ffbc63,#d46b02″][vc_column][stm_cta button_color=”custom” button_custom_color=”#0077c2″ icon_custom_color=”#ffffff” button_icon_pos=”right” button_icon=”stmicon-chevron-right” style=”style_6″ link=”url:aryasoft.com.tr/contacts |title:İletişim”] Size ve Veritabanlarınıza Yardımcı Olmak İçin Bekliyoruz! [/stm_cta][/vc_column][/vc_row][vc_row css=”.vc_custom_1501845139892{margin-top: 50px !important;margin-bottom: 25px !important;}”][/vc_row]