Linux用のSQLServer2017のリリース以来、Microsoftはゲーム全体を大幅に変更しました。これにより、有名なリレーショナルデータベースのまったく新しい可能性が生まれ、それまでWindowsスペースでしか利用できなかったものが提供されました。
純粋主義者のDBAは、すぐに使えるSQL Server 2019 Linuxバージョンには、Windows版に関して、機能に関していくつかの違いがあることをすぐに教えてくれることを知っています。
- SQLServerエージェントなし
- ファイルストリームなし
- システム拡張ストアドプロシージャ(xp_cmdshellなど)はありません
しかし、私は「両方ができることと、少なくともある程度は比較できるとしたらどうなるだろうか」と考えるほど興味をそそられました。そこで、いくつかのVMでトリガーを引き、いくつかの簡単なテストを準備し、データを収集して提示しました。どうなるか見てみましょう!
最初の考慮事項
各VMの仕様は次のとおりです。
- Windows
- Windows 10 OS
- 4つのvCPU
- 4 GB RAM
- 30 GB SSD
- Linux
- Ubuntu Server 20.04 LTS
- 4つのvCPU
- 4 GB RAM
- 30 GB SSD
SQL Serverバージョンでは、両方のオペレーティングシステム用に最新のものを選択しました:SQL Server 2019 Developer Edition CU10
各デプロイメントで有効にされたのは、インスタントファイル初期化(Linuxではデフォルトで有効、Windowsでは手動で有効)のみでした。それ以外は、残りの設定はデフォルト値のままでした。
- Windowsでは、インストールウィザードを使用してインスタントファイル初期化を有効にすることを選択できます。
この投稿では、Linuxでのインスタントファイル初期化作業の具体性については説明しません。ただし、後で読むことができる専用の記事へのリンクを残しておきます(技術的な面で少し重くなるので注意してください)。
テストには何が含まれますか?
- 各SQLServer2019インスタンスで、テストデータベースを展開し、1つのフィールド(NVARCHAR(MAX))のみを含む1つのテーブルを作成しました。
- ランダムに生成された1,000,000文字の文字列を使用して、次の手順を実行しました。
- *X行数をテストテーブルに挿入します。
- INSERTステートメントの完了にかかった時間を測定します。
- MDFおよびLDFファイルのサイズを測定します。
- テストテーブルのすべての行を削除します。
- **DELETEステートメントを完了するのにかかった時間を測定します。
- LDFファイルのサイズを測定します。
- テストデータベースを削除します。
- テストデータベースを再作成します。
- 同じサイクルを繰り返します。
* Xは、1,000、5,000、10,000、25,000、および50,000行に対して実行されました。
** TRUNCATEステートメントがより効率的に機能することは知っていますが、ここでの私のポイントは、各OSでの削除操作に対して各トランザクションログがどの程度適切に管理されているかを証明することです。
さらに深く掘り下げたい場合は、ランダムな文字列を生成するために使用したWebサイトに進むことができます。
各オペレーティングシステムでのテストに使用したTSQLコードのセクションは次のとおりです。
LinuxTSQLコード
データベースとテーブルの作成
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)'
WindowsTSQLコード
データベースとテーブルの作成
DROP DATABASE IF EXISTS test
CREATE DATABASE test
ON
(FILENAME= 'S:\Program Files\Microsoft SQL Server\MSSQL15.WINDOWS\MSSQL\DATA\test.mdf', NAME = test, FILEGROWTH = 128MB)
LOG ON
(FILENAME= ''S:\Program Files\Microsoft SQL Server\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'
次のスクリーンショットは、データベースに何も保存されていない場合のデータファイルのサイズを示しています。
インスタントファイル初期化が有効になっているかどうかを確認するためのクエリ
SELECT
servicename,
instant_file_initialization_enabled
FROM sys.dm_server_services
WHERE servicename = 'SQL Server (MSSQLSERVER)'
INSERTステートメントを実行するためのスクリプト:
@limit->ここで、テストテーブルに挿入する行数を指定しました
Linuxの場合、SQLCMDを使用してスクリプトを実行したため、最後にDATEDIFF関数を配置しました。実行全体にかかる秒数がわかります(Windowsバリアントの場合、SQL Server Management Studioのタイマーを垣間見ることができました)。
「XXXX」の代わりに、1,000,000文字の文字列全体が使用されます。私はそれをこの投稿でうまく提示するためだけにそのように置いています。
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';
得られた結果
すべてのサイズはMBで表されます。すべてのタイミング測定値は秒単位で表されます。
挿入時間 | 1,000レコード | 5,000レコード | 10,000レコード | 25,000レコード | 50,000レコード |
Linux | 4 | 23 | 43 | 104 | 212 |
ウィンドウズ | 4 | 28 | 172 | 531 | 186 |
サイズ(MDF) | 1,000レコード | 5,000レコード | 10,000レコード | 25,000レコード | 50,000レコード |
Linux | 264 | 1032 | 2056 | 5128 | 10184 |
ウィンドウズ | 264 | 1032 | 2056 | 5128 | 10248 |
サイズ(LDF) | 1,000レコード | 5,000レコード | 10,000レコード | 25,000レコード | 50,000レコード |
Linux | 104 | 264 | 360 | 552 | 148 |
ウィンドウズ | 136 | 328 | 392 | 456 | 584 |
削除時間 | 1,000レコード | 5,000レコード | 10,000レコード | 25,000レコード | 50,000レコード |
Linux | 1 | 1 | 74 | 215 | 469 |
ウィンドウズ | 1 | 63 | 126 | 357 | 396 |
DELETEサイズ(LDF) | 1,000レコード | 5,000レコード | 10,000レコード | 25,000レコード | 50,000レコード |
Linux | 136 | 264 | 392 | 584 | 680 |
ウィンドウズ | 200 | 328 | 392 | 456 | 712 |
重要な洞察
- MDFのサイズは、テスト全体でほぼ一貫しており、最後にわずかに変化しました(ただし、あまりクレイジーではありません)。
- INSERTのタイミングは、Windowsが「ラウンドに勝った」最後の部分を除いて、ほとんどの部分でLinuxの方が優れていました。
- トランザクションログファイルのサイズは、INSERTの各ラウンド後にLinuxでより適切に処理されました。
- DELETEのタイミングは、Windowsが「ラウンドに勝った」最後の部分を除いて、ほとんどの部分でLinuxの方が優れていました(Windowsが最後のINSERTラウンドにも勝ったのは不思議です)。
- DELETEの各ラウンド後のトランザクションログファイルのサイズは、2つの間の浮き沈みの点でほぼ同点でした。
- 100,000行でテストしたかったのですが、ディスク容量が少し不足していたため、50,000行に制限しました。
結論
このテストから得られた結果に基づくと、LinuxのバリアントがWindowsのバリアントよりも指数関数的に優れていると主張する強い理由はないと思います。もちろん、これは決してそのような決定を下すためにあなたが根拠となることができる正式なテストではありません。しかし、演習自体は私にとって十分に興味深いものでした。
Windows用のSQLServer2019は、バックグラウンドでのGUIレンダリングが原因で、少し遅れることがあると思います。これは、フェンスのUbuntuサーバー側では発生していません。
(少なくともこの記事の執筆時点では)Windows専用の機能に大きく依存している場合は、ぜひそれを選択してください。そうでなければ、どちらか一方を優先することで悪い選択をすることはほとんどありません。