مقدمه

از زمان انتشار SQL Server 2017 برای لینوکس، مایکروسافت تقریباً کل مبنا را تغییر داده است. مایکروسافت یک‌ دنیای کاملاً جدید از امکانات را برای پایگاه ‌داده رابطه‌ ای فعال کرد و آنچه را که تا آن زمان فقط در فضای ویندوز در دسترس بود برای لینوکس نیز ارائه می ‌کرد.
یک متخصص دیتابیس (DBA) خواهد گفت که نسخه لینوکس SQL Server 2019 چندین تفاوت از نظر ویژگی با نسخه ویندوز خود دارد، مانند:

  •  بدون SQL Server Agent
  • بدون FileStream
  •  نداشتن رویه ‌های ذخیره ‌شده توسعه ‌یافته (Store Procedure) سیستم (مانند xp_cmdshell)

با این ‌وجود تصمیم گرفتم تا آنها را با هم مقایسه کنم؛ بنابراین، چند ماشین مجازی ساختم و چند آزمایش ساده را آماده کردم و داده‌ هایی را جمع ‌آوری کردم تا به شما ارائه کنم. با من همراه باشید تا این تفاوت ‌ها را ببینیم.

ملاحظات اولیه

در این قسمت مشخصات هر (ماشین مجازی) VM آمده است:

Windows

  • سیستم ‌عامل ویندوز 10
  •  vCPU 4
  • رم 4 گیگابایت
  • 30 گیگابایت SSD

لینوکس

  • سرور اوبونتو 20.04 LTS
  •  4 vCPU
  •  رم 4 گیگابایت
  •  30 گیگابایت SSD

برای نصب SQL Server، جدیدترین نسخه را برای هر دو سیستم‌ عامل انتخاب کردم: SQL Server 2019 Developer Edition CU10

در هر نصب، تنها چیزی که فعال می‌شد، Instant File Initialization بود (به طور پیش ‌فرض در لینوکس فعال است، به‌صورت دستی در ویندوز فعال می ‌شود). به‌غیراز آن، مقادیر پیش ‌فرض برای بقیه تنظیمات باقی می ‌ماند.
در ویندوز، می‌توانید Instant File Initialization را از طریق Wizard نصب و فعال شود.

در این پست ویژگی کار Instant File Initialization در لینوکس را توضیح نمی ‌دهد. با این‌ حال، شما می ‌توانید بعداً به مقالات مرتبط مراجعه کنید (توجه داشته باشید که از نظر فنی کمی سنگین می ‌باشد).

 

تست شامل چه مواردی است؟

1. در هر SQL Server 2019، من یک پایگاه‌ داده آزمایشی را نصب کردم و یک جدول با تنها یک فیلد (NVARCHAR(MAX)) ایجاد کردم.
2. با استفاده از یک ‌رشته تولید شده به‌ صورت تصادفی از 1000000 کاراکتر، مراحل زیر را انجام دادم:

  •  *تعداد X ردیف را در جدول تست وارد کنید.
  •  مدت‌ زمان تکمیل عبارت INSERT را اندازه بگیرید.
  •  اندازه فایل ‌های MDF و LDF را اندازه‌ گیری کنید.
  •  تمام سطرهای جدول تست را حذف کنید.
  •  ** اندازه ‌گیری زمان لازم برای تکمیل عبارت DELETE.
  •  اندازه فایل LDF را اندازه‌ گیری کنید.
  •  پایگاه‌ داده تست را حذف کنید.
  •  دوباره پایگاه ‌داده تست را ایجاد کنید.
  •  همان چرخه را تکرار کنید.
  • X برای 1000، 5000، 10000، 25000 و 50000 ردیف اجرا شد.
    **من می‌ دانم که یک دستور TRUNCATE کار را با کارایی بیشتری انجام می ‌دهد، اما هدف من در اینجا این است که ثابت کنم هر

گزارش تراکنش چقدر برای عملیات حذف در هر سیستم‌ عامل محاسبه می‌ شود.
در اینجا بخش ‌هایی از کد TSQL است که برای آزمایش ‌ها در هر سیستم ‌عامل استفاده شده است:

کدهای لینوکس TSQL

ایجاد پایگاه‌داده و جداول

DROP DATABASE IF EXISTS test
 CREATE DATABASE test
 ON
 (FILENAME= '/var/opt/mssql/data/test.mdf', NAME = test, FILEGROWTH = 128MB)
 LOG ON 
(FILENAME= '/var/opt/mssql/data/test_log.ldf',NAME = test_log, FILEGROWTH = 64MB);
 CREATE TABLE test.dbo.ubuntu
(long_string NVARCHAR(MAX) NOT NULL 
)

 

اندازه فایل‌ های MDF و LDF برای پایگاه‌ داده تست

SELECT 
DB_NAME(database_id) AS 'DB',
type_desc AS 'Type', 
state_desc AS 'State', 
CONVERT(DECIMAL(10,2),
size*8/1024) AS 'Size', 
CONVERT(DECIMAL(10,2),
growth*8/1024) AS 'Growth' 
FROM sys.master_files 
WHERE DB_NAME(database_id) = 'test'

 

اسکرین ‌شات زیر اندازه فایل‌ های داده را زمانی که چیزی در پایگاه ‌داده ذخیره نشده است را نشان می ‌دهد:

SELECT 
       servicename,
       instant_file_initialization_enabled
FROM   sys.dm_server_services
WHERE  servicename = 'SQL Server (MSSQLSERVER)'

کدهای TSQL ویندوز

ایجاد پایگاه‌داده و جداول

DROP DATABASE IF EXISTS test 
CREATE DATABASE test 
ON 
(FILENAME='S:\ProgramFiles\MicrosoftSQLServer\MSSQL15.WINDOWS\MSSQL\DATA\test.mdf', NAME = test, FILEGROWTH = 128MB) 
LOG ON 
(FILENAME=''S:\ProgramFiles\MicrosoftSQLServer\MSSQL15.WINDOWS\MSSQL\DATA\test_log.ldf',NAME = test_log, FILEGROWTH = 64MB); 
CREATE TABLE test.dbo.windows( 
long_string NVARCHAR(MAX) NOT NULL 
)

 

اندازه فایل‌ های MDF و LDF برای پایگاه‌ داده تست

 

SELECT
 DB_NAME(database_id) AS 'DB', 
type_desc AS 'Type', state_desc AS 'State', 
CONVERT(DECIMAL(10,2),size*8/1024) AS 'Size', 
CONVERT(DECIMAL(10,2),growth*8/1024) AS 'Growth' 
FROM sys.master_files 
WHERE DB_NAME(database_id) = 'test'

اسکرین ‌شات زیر اندازه فایل ‌های داده را زمانی که چیزی در پایگاه ‌داده ذخیره نشده است نشان می ‌دهد:

 

 

در زیر پرس ‌و جوهایی است برای تعیین اینکه آیا Instant File Initialization فعال است یا خیر:

SELECT 
servicename, 		
instant_file_initialization_enabled 		
FROM sys.dm_server_service    	
WHERE servicename = 'SQL Server (MSSQLSERVER)'	

 

اسکریپت برای اجرای دستور INSERT:

limit@،در این قسمت تعداد سطرهایی را برای درج در جدول تست مشخص کردم.
برای لینوکس، از آنجایی‌که من اسکریپت را با استفاده از SQLCMD اجرا کردم، تابع DATEDIFF را در انتهای آن قرار دادم. این تابع به من اجازه می ‌دهد بفهمم کل اجرا چند ثانیه طول می ‌کشد (برای نوع ویندوز، می ‌توانم به‌ سادگی نگاه کلی به تایمر در SQL Server Management Studio داشته باشم).

SET NOCOUNT ON
GO 
DECLARE @StartTime DATETIME; 
DECLARE @i INT; 
DECLARE @limit INT; SET @StartTime = GETDATE(); 
SET @i = 0; 
SET @limit = 1000; 
WHILE(@i < @limit) 
BEGIN 
INSERT INTO test.dbo.ubuntu VALUES('XXXX'); 
SET @i = @i + 1 
END 
SELECT DATEDIFF(SECOND,@StartTime,GETDATE()) AS 'Elapsed Seconds';

 

کل رشته 1,000,000 کاراکتری به جای «XXXX» می رود. من آن را فقط برای زیباتر شدن در این پست قرار می ‌دهم.

SET NOCOUNT 
ON 
GO 
DECLARE @StartTime DATETIME; 
DECLARE @i INT; 
DECLARE @limit INT; SET @StartTime = GETDATE(); 
SET @i = 0;
SET @limit = 1000; 
WHILE(@i < @limit) 
BEGIN 
INSERT 
INTO test.dbo.ubuntu VALUES('XXXX'); 
SET @i = @i + 1 
END 
SELECT DATEDIFF(SECOND,@StartTime,GETDATE()) AS 'Elapsed Seconds';

 

اسکریپت برای اجرای دستور DELETE

 

SET NOCOUNT 
ON 
GO 
DECLARE @StartTime DATETIME; 
SET @StartTime = GETDATE(); 
DELETE FROM test.dbo.ubuntu; 
SELECT DATEDIFF(SECOND,@StartTime,GETDATE()) AS 'Elapsed Seconds';

همه اندازه‌ ها بر حسب مگابایت بیان شده است. تمام اندازه ‌گیری ‌های زمان ‌بندی بر حسب ثانیه بیان شده است.

INSERT Time1,000 records5,000 records10,000 records25,000 records50,000 records
Linux42343104212
Windows428172531186
Size (MDF)1,000 records5,000 records10,000 records25,000 records50,000 records
Linux26410322056512810184
Windows26410322056512810248
Size (LDF)1,000 records5,000 records10,000 records25,000 records50,000 records
Linux104264360552148
Windows136328392456584
DELETE Time1,000 records5,000 records10,000 records25,000 records50,000 records
Linux1174215469
Windows163126357396
DELETE Size (LDF)1,000 records5,000 records10,000 records25,000 records50,000 records
Linux136264392584680
Windows200328392456712

نتیجه‌ های کلیدی

  •  اندازه MDF در کل آزمایش تقریباً ثابت بود، در پایان کمی متفاوت بود (اما چیز خیلی عجیبی نبود).
  •  زمان‌ بندی INSERTها در لینوکس در اکثر موارد بهتر بود، به جز موارد پایانی که ویندوز “پیروز شد”.
  • پس از هر دور INSERT، اندازه فایل گزارش تراکنش در لینوکس بهتر مدیریت می‌ شد.
  •  زمان ‌بندی DELETEها در لینوکس در اکثر موارد بهتر بود، به جز موارد انتهایی که ویندوز بهتر بود. (جالب است که ویندوز در دور نهایی INSERT نیز برنده شد).
  •  اندازه فایل ‌های گزارش تراکنش‌ ها پس از هر دور DELETE، از نظر فراز و نشیب بین هر دو تقریباً یکسان بود.
  • من دوست داشتم با 100000 ردیف تست کنم، اما فضای دیسک کمی داشتم، بنابراین آن را روی 50000 گذاشتم.

نتیجه

بر اساس نتایج به‌ دست‌ آمده از این آزمایش، می‌ توانم بگویم هیچ دلیل محکمی برای ادعای اینکه نوع لینوکس به طور تصاعدی بهتر از نسخه ویندوزی خود عمل می ‌کند وجود ندارد. البته، این به ‌هیچ ‌وجه یک آزمون رسمی نیست که بتوانید چنین تصمیمی را اتخاذ کنید. با این‌ حال، خود تمرین برای من به‌ اندازه کافی جالب بود.

حدس می‌زنم که SQL Server 2019 برای ویندوز به دلیل رندر رابط کاربری گرافیکی در پس ‌زمینه که در سمت سرور اوبونتو انجام نمی ‌شود، گاهی اوقات کمی عقب می ‌افتد (نه خیلی).

اگر به‌ شدت به ویژگی‌ ها و قابلیت ‌هایی که مختص ویندوز هستند (حداقل در زمان نگارش این مقاله) تکیه می ‌کنید، حتماً آن را دنبال کنید. در غیر این صورت، به ‌سختی می ‌توانید انتخاب بدی را با انتخاب یکی از دیگری انجام دهید.