SQL Server پیمایش بهینه سطرها بدون Cursor

راهکارهای پیشرفته برای پیمایش سطرهای جدول در SQL Server بدون نیاز به Cursor

استفاده از Cursorها در SQL Server برای پیمایش و پردازش سطر به سطر نتایج، می‌تواند منجر به مشکلات جدی در عملکرد شود، به خصوص در مجموعه داده‌های بزرگ. این رویکرد معمولاً منابع زیادی را مصرف می‌کند و به دلیل ماهیت سطر به سطر خود، کارایی پایینی دارد. خوشبختانه، SQL Server جایگزین‌های کارآمدتری را برای دستیابی به همین هدف ارائه می‌دهد که به بهبود چشمگیر عملکرد پایگاه داده کمک می‌کند.

یکی از روش‌های رایج برای پیمایش سطرهای جدول بدون Cursor، استفاده از حلقه WHILE است. این روش به شما امکان می‌دهد تا با مدیریت یک متغیر شمارنده، سطرها را یک به یک پردازش کنید. برای پیاده‌سازی این الگو، ابتدا باید یک متغیر برای نگه داشتن شناسه (ID) آخرین سطر پردازش شده تعریف کنید. سپس، در هر مرحله از حلقه، شناسه سطر بعدی را برداشته و پس از انجام عملیات مورد نظر، متغیر شمارنده را به‌روزرسانی کنید.


DECLARE @id INT = 0;
DECLARE @maxId INT;

SELECT @maxId = MAX(id) FROM YourTable;

WHILE @id <= @maxId
BEGIN
    -- Perform operations on the row with current @id
    SELECT * FROM YourTable WHERE id = @id;

    SET @id = @id + 1;
END;
    

روش دیگر استفاده از عبارت جدول مشترک بازگشتی (Recursive Common Table Expression یا CTE) است. این تکنیک به ویژه برای سناریوهایی که نیاز به پردازش سلسله مراتبی یا تکراری داده‌ها دارید، بسیار قدرتمند است. CTE بازگشتی شامل یک بخش “لنگر” (Anchor) برای شروع و یک بخش “بازگشتی” (Recursive) است که به خودش ارجاع می‌دهد تا زمانی که شرط پایانی برآورده شود.


WITH RecursiveCTE AS (
    -- Anchor member (initial query)
    SELECT id, column1, column2
    FROM YourTable
    WHERE id = 1 -- Starting point

    UNION ALL

    -- Recursive member
    SELECT T.id, T.column1, T.column2
    FROM YourTable AS T
    INNER JOIN RecursiveCTE AS RCTE ON T.id = RCTE.id + 1
    WHERE T.id <= (SELECT MAX(id) FROM YourTable)
)
SELECT id, column1, column2
FROM RecursiveCTE
OPTION (MAXRECURSION 0); -- To allow unlimited recursion, or set a specific number
    

یکی از مدرن‌ترین و کارآمدترین رویکردها برای تقسیم‌بندی و پیمایش داده‌ها، بهره‌گیری از توابع پنجره‌ای مانند ROW_NUMBER() در کنار OFFSET و FETCH است. این ترکیب به شما امکان می‌دهد تا مجموعه‌های کوچکی از سطرها (صفحات) را در هر بار بازیابی کنید، که برای پیاده‌سازی صفحه‌بندی (Paging) یا پردازش دسته‌ای (Batch Processing) بسیار مفید است. ROW_NUMBER() یک شماره سطر یکتا به هر سطر در مجموعه نتایج اختصاص می‌دهد، و سپس OFFSET و FETCH به شما اجازه می‌دهند تا از یک نقطه شروع مشخص، تعداد معینی از سطرها را بازیابی کنید.


DECLARE @pageSize INT = 1000; -- Number of rows to process in each batch
DECLARE @pageNumber INT = 0;
DECLARE @totalRows INT;

SELECT @totalRows = COUNT(*) FROM YourTable;

WHILE @pageNumber * @pageSize < @totalRows
BEGIN
    SELECT *
    FROM YourTable
    ORDER BY id
    OFFSET (@pageNumber * @pageSize) ROWS
    FETCH NEXT @pageSize ROWS ONLY;

    SET @pageNumber = @pageNumber + 1;
END;
    

انتخاب روش مناسب به نیازهای خاص، حجم داده‌ها و پیچیدگی عملیات بستگی دارد. در بیشتر موارد، استفاده از راهکارهای مبتنی بر مجموعه (Set-based solutions) مانند ROW_NUMBER() و CTE، عملکرد به مراتب بهتری نسبت به Cursorها و حتی حلقه‌های WHILE ساده ارائه می‌دهد، زیرا SQL Server می‌تواند این عملیات را به صورت موازی و بهینه پردازش کند. این رویکردهای جایگزین، به توسعه‌دهندگان و مدیران پایگاه داده کمک می‌کنند تا کارایی سیستم‌های SQL Server خود را به حداکثر برسانند.

cursorsql serverاسکریپتاموزش SqlServer
Comments (0)
Add Comment