واکشی تصادفی رکوردها از جدول در SQL Server

گزینه TABLESAMPLE

این option در هنگام واکشی داده ها، ردیف های تصادفی را از یک جدول برمی گرداند. می توان از آن برای دریافت نمونه ای از ردیف ها از جدول استفاده کرد. البته دقیقا همان درصد ردیف های مشخص شده را بر نمی گرداند.

PERCENT) (10 SELECT * FROM Person.Person TABLESAMPLE

کوئری بالا تقریبا ۱۰٪ ردیفها را برمیگرداند (دقیق نیست). به نتیجه در messages توجه کنید:

هر بار تعداد ردیفهای متفاوتی را نزدیک همان ۱۰ درصد برمیگرداند:

Select

(SELECT COUNT(*) FROM Person.Person

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT) ) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT) ) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT) ) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT) ) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT) ) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT) ) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT) ) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT) ) 

نکته: کوئری بالا معادل کوئری زیر است:

()SELECT TOP 10 Percent * FROM Person.Person ORDEBY NEWID

نکته: اگر بخواهیم مثلا دقیقا دو ردیف بصورت تصادفی واکشی کند از روش زیر استفاده میکنیم:

SٍELECT TOP 2 * FROM Person.Person TABLESAMPLE (2 rows)

استفاده از گزینه REPEATABLE

گزینه REPEATABLE باعث می شود یک نمونه انتخاب شده دوباره برگردانده شود. هنگامی که REPEATABLE با همان مقدار repeat_seed مشخص می شود(مقدار جلوی REPEATABLE، SQL Server همان زیرمجموعه ردیف ها را برمی گرداند، تا زمانی که هیچ تغییری در جدول ایجاد نشده باشد. هنگامی که REPEATABLE با یک مقدار repeat_seed متفاوت مشخص می شود، SQL Server معمولاً نمونه متفاوتی از ردیف های جدول را برمی گرداند. اقدامات زیر در جدول به عنوان تغییرات در نظر گرفته می شوند: درج، به روز رسانی، حذف، rebuild ایندکس، و index defragmenting، بازیابی پایگاه داده و attatch کردن پایگاه داده.

مثال را ببینید:

Select

(SELECT COUNT(*) FROM Person.Person,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT)  REPEATABLE(1)) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT)  REPEATABLE(1)) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT)  REPEATABLE(1)) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT)  REPEATABLE(1)) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT)  REPEATABLE(1)) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT)  REPEATABLE(1)) 

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT)  REPEATABLE(1)) ,

(SELECT COUNT(*) FROM Person.Person TABLESAMPLE (10 PERCENT)  REPEATABLE(1)) 

نکته: TableSample را نمی توان برای Derived Tables، جداول از Linked Servers، و tables derived from table-valued functions، rowset functions یا OPENXML اعمال کرد. TABLESAMPLE را نمی توان در تعریف یک View یا یک inline table-valued function بکار برد.

عبارت SET ROWCOUNT

SET ROWCOUNT n

پس از برگرداندن تعداد ردیفهای درخواستی از هر جدول (یا function)، موجب توقف پردازش کوئری خواهد شد.

مثلا ما بخواهیم از این به بعد از هر جدول SELECT گرفتیم، تنها دو رکورد از آن را برای ما بیاورد:

SET ROWCOUNT 2

SELECT * FROM Production.ProductCategory

SELECT * FROM Production.ProductSubCategory

SELECT * FROM Production.Product

همانطور که متوجه شدید این عبارت همان کار Top(n) را میکند. اما اگر شما میخواستید مثلا برای تمام جداول مدنظر خود، تنها دو ردیف اول آنرا را مشاهده کنید باید به ازای هر کوئری در SELECT، از TOP(2) استفاده کنید. اما با تنظیم این تابع،  بابت هر کوئری SELECT، دوردیف اول را به شما بر خواهد گرداند.

به این نکته توجه داشته باشید SET ROWCOUNT تنها به ازای سژن جاری تنظیم خواهد شد و در سژن دیگر معتبر نخواهد بود.

درصورتیکه بخواهید دوباره به حالت معمول پردازش و نمایش تمام رکوردهای کوئری برگردید کافیست جلوی این تابع عدد 0 را قرار دهید:

SET ROWCOUNT 0

عبارت SET NOCOUNT

با فعال کردن این عبارت، در خروجی تمام ردیفهای موجود در جدول یا تابع یا پروسیجر را به شما برمیگرداند، اما در messages، پیام حاوی اینکه چه تعداد ردیف  تحت تاثیر قرار گرفته اند را نشان نخواهد داد. 

همچنین با فعال کردن این قابلیت میتوان هنگام درج کردن (insert) در یک جدول، از نمایش و اعلام درج یکی یکی رکوردها جلوگیری کرد.

برای مثال در حالت عادی یک جدول ایجاد و چند رکورد درج می کنیم:

 CREATE TABLE tblEmployeeDemo
  Id      INT)
   PRIMARY KEY,
   EmpName NVARCHAR(50),
  Gender  NVARCHAR(10),
 ;(
GO
INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (1, N‘Grace’, N‘Female’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (2, N‘Gordon’, N‘Male’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (3, N‘Jaime’, N‘Female’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (4, N‘Ruben’, N‘Female’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (5, N‘Makayla’, N‘Male’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (6, N‘Barry’, N‘Female’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (7, N‘Ramon’, N‘Male’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (8, N‘Douglas’, N‘Male’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (9, N‘Julian’, N‘Female’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (10, N‘Sarah’, N‘Female’)
  GO

همانطور که مشاهده میکنید به ازای هر درج صورت گرفته، آنرا در خروجی اعلان میکند:

The output '1 row affected' in SSMS

فرض کنید یک میلیون ردیف در جدول وارد کرده اید و برای هر رکورد، این پیام را دریافت می کنید. همانطور که می بینید، پیام مفیدی نیست و اطلاعات مرتبطی را ارائه نمی دهد.

در مورد select هم اگر به تب messages برویم پیام تعداد رکورد تحت تاثیر قرار گرفته را به ما میدهد:

 * SELECT
  FROM tblEmployeeDemo
Result and message tab in SSMS

SET NOCOUNT ON

حال ما این قابلیت را فعال میکنیم و رکوردهای جدول را پاک و مجددا درج را انجام می دهیم:

TRUNCATE TABLE tblEmployeeDemo
  GO
  SET NOCOUNT ON
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (1, N‘Grace’, N‘Female’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (2, N‘Gordon’, N‘Male’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (3, N‘Jaime’, N‘Female’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (4, N‘Ruben’, N‘Female’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (5, N‘Makayla’, N‘Male’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (6, N‘Barry’, N‘Female’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (7, N‘Ramon’, N‘Male’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (8, N‘Douglas’, N‘Male’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (9, N‘Julian’, N‘Female’)
  GO
  INSERT [dbo].[tblEmployeeDemo] ([Id], [EmpName], [Gender]) VALUES (10, N‘Sarah’, N‘Female’)
  GO

وقتی درجهای بالا را انجام میدهیمم دیگر هیچ پیامی مبنی بر اینکه این تعداد رکورد درج شد نمیگیریم و هر موقع پردازش کوئری تمام شد تنها پیغام عملیات با موفقیت انجام شد را میدهد:

Effect of SET NOCOUNT ON

با فعال بودن این قابلیت اگر از جدول فوق select بگیریم دیگر اینکه چه تعداد رکورد تحت تاثیر واکشی اطلاعات قرار گرفتند را به ما نشان نخواهد داد:

Effect of NOCOUNT messages on select statement

برای تابع هم چون حکم جدول را دارد این قابلیت کار میکند.

برای پروسیجر هم این قابلیت کار میکند اما به شرطی که به هنگام تعریف آن پروسیجر این قابیلت را در بدنه پروسیجر قرار دهیم و آنجا آنرا فعال کنیم و بعد آنرا هر جا نیاز بود فراخوانی کنیم تا رکوردهای تحت تاثیر را نشان ندهد:

ALTER PROCEDURE SP_tblEmployeeDemo
  AS
      BEGIN
          SET NOCOUNT ON
           * SELECT 
          FROM tblEmployeeDemo
      ;END
GO

مزیت: با فعال کردن این قابلیت، در حجم زیاد رکورد بهنگام واکشی اطلاعات از جدول یا هر گونه اعمال DML (درج، بروزرسانی، حذف) در جدول، به افزایش عملکرد سیستم کمک خواهد کرد.

برای بازگشت به حالت عادی و نمایش تعداد ردیفهای تحت تاثیر این عبارت را غیرفعال میکنیم:

 SET NOCOUNT OFF

نکته: می‌توانیم از متغیر سیستمی ROWCOUNT@@ برای دریافت تعداد ردیف‌های تحت تاثیر در SQL Server استفاده کنیم. عبارت NOCOUNT ON هیچ تاثیری بر تابع ROWCOUNT@@ ندارد.

 

برچسب ها: بدون برچسب

نظر بگذارید

آدرس ایمیل شما منتشر نخواهد شد. قسمتهای مورد نیاز علامت گذاری شده اند *