Siden udgivelsen af SQL Server 2017 til Linux har Microsoft stort set ændret hele spillet. Det muliggjorde en helt ny verden af muligheder for deres berømte relationsdatabase, der tilbød det, der indtil da kun var tilgængeligt i Windows-området.
Jeg ved, at en puristisk DBA ville fortælle mig med det samme, at den ude af kassen SQL Server 2019 Linux-version har adskillige forskelle med hensyn til funktioner med hensyn til Windows-modstykket, såsom:
- Ingen SQL Server Agent
- Ingen FileStream
- Ingen systemudvidede lagrede procedurer (f.eks. xp_cmdshell)
Men jeg blev nysgerrig nok til at tænke "hvad nu hvis de kan sammenlignes, i det mindste til en vis grad, med ting, som begge kan gøre?" Så jeg trykkede på aftrækkeren på et par VM'er, forberedte nogle simple tests og indsamlede data til at præsentere for dig. Lad os se, hvordan tingene udvikler sig!
Indledende overvejelser
Her er specifikationerne for hver VM:
- Windows
- Windows 10 OS
- 4 vCPU'er
- 4 GB RAM
- 30 GB SSD
- Linux
- Ubuntu Server 20.04 LTS
- 4 vCPU'er
- 4 GB RAM
- 30 GB SSD
Til SQL Server-versionen valgte jeg den allernyeste til begge operativsystemer:SQL Server 2019 Developer Edition CU10
I hver implementering var det eneste aktiverede øjeblikkelig filinitialisering (aktiveret som standard på Linux, aktiveret manuelt på Windows). Bortset fra det forblev standardværdierne for resten af indstillingerne.
- I Windows kan du vælge at aktivere øjeblikkelig filinitialisering med installationsguiden.
Dette indlæg vil ikke dække specificiteten af Instant File Initialization-arbejdet i Linux. Jeg vil dog efterlade dig et link til den dedikerede artikel, som du kan læse senere (bemærk det, da det bliver lidt tungt på den tekniske side).
Hvad omfatter testen?
- I hver SQL Server 2019-instans installerede jeg en testdatabase og oprettede én tabel med kun ét felt (en NVARCHAR(MAX)).
- Ved at bruge en tilfældigt genereret streng på 1.000.000 tegn udførte jeg følgende trin:
- *Indsæt X antal rækker i testtabellen.
- Mål, hvor lang tid det tog at fuldføre INSERT-sætningen.
- Mål størrelsen af MDF- og LDF-filerne.
- Slet alle rækker i testtabellen.
- **Mål, hvor lang tid det tog at fuldføre DELETE-sætningen.
- Mål størrelsen af LDF-filen.
- Slet testdatabasen.
- Opret testdatabasen igen.
- Gentag den samme cyklus.
*X blev udført for 1.000, 5.000, 10.000, 25.000 og 50.000 rækker.
**Jeg ved, at en TRUNCATE-sætning udfører arbejdet meget mere effektivt, men min pointe her er at bevise, hvor godt hver transaktionslog administreres til sletningsoperationen i hvert operativsystem.
Du kan gå videre til webstedet, jeg brugte til at generere den tilfældige streng, hvis du vil grave dybere.
Her er sektionerne af TSQL-koden, jeg brugte til test i hvert operativsystem:
Linux TSQL-koder
Oprettelse af database og tabel
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
)
Størrelsen af MDF- og LDF-filerne til testdatabasen
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'
Nedenstående skærmbillede viser datafilernes størrelse, når intet er gemt i databasen:
Forespørgsler for at afgøre, om øjeblikkelig filinitialisering er aktiveret
SELECT
servicename,
instant_file_initialization_enabled
FROM sys.dm_server_services
WHERE servicename = 'SQL Server (MSSQLSERVER)'
Windows TSQL-koder
Oprettelse af database og tabel
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
)
Størrelsen af MDF- og LDF-filerne til testdatabasen
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'
Følgende skærmbillede viser datafilernes størrelse, når intet er gemt i databasen:
Forespørgsel for at afgøre, om øjeblikkelig filinitialisering er aktiveret
SELECT
servicename,
instant_file_initialization_enabled
FROM sys.dm_server_services
WHERE servicename = 'SQL Server (MSSQLSERVER)'
Script til at udføre INSERT-sætningen:
@limit -> her har jeg angivet antallet af rækker, der skal indsættes i testtabellen
For Linux, da jeg udførte scriptet ved hjælp af SQLCMD, satte jeg DATEDIFF-funktionen til allersidst. Det fortæller mig, hvor mange sekunder hele udførelsen tager (for Windows-varianten kunne jeg simpelthen have taget et glimt af timeren i SQL Server Management Studio).
Hele strengen på 1.000.000 tegn går i stedet for 'XXXX'. Jeg siger det sådan kun for at præsentere det pænt i dette indlæg.
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';
Script til at udføre DELETE-sætningen
SET NOCOUNT ON
GO
DECLARE @StartTime DATETIME;
SET @StartTime = GETDATE();
DELETE FROM test.dbo.ubuntu;
SELECT DATEDIFF(SECOND,@StartTime,GETDATE()) AS 'Elapsed Seconds';
De opnåede resultater
Alle størrelser er udtrykt i MB. Alle tidsmålinger er udtrykt i sekunder.
INDSÆT tidspunkt | 1.000 poster | 5.000 poster | 10.000 poster | 25.000 poster | 50.000 poster |
Linux | 4 | 23 | 43 | 104 | 212 |
Windows | 4 | 28 | 172 | 531 | 186 |
Størrelse (MDF) | 1.000 poster | 5.000 poster | 10.000 poster | 25.000 poster | 50.000 poster |
Linux | 264 | 1032 | 2056 | 5128 | 10184 |
Windows | 264 | 1032 | 2056 | 5128 | 10248 |
Størrelse (LDF) | 1.000 poster | 5.000 poster | 10.000 poster | 25.000 poster | 50.000 poster |
Linux | 104 | 264 | 360 | 552 | 148 |
Windows | 136 | 328 | 392 | 456 | 584 |
SLETT tidspunkt | 1.000 poster | 5.000 poster | 10.000 poster | 25.000 poster | 50.000 poster |
Linux | 1 | 1 | 74 | 215 | 469 |
Windows | 1 | 63 | 126 | 357 | 396 |
SLET Størrelse (LDF) | 1.000 poster | 5.000 poster | 10.000 poster | 25.000 poster | 50.000 poster |
Linux | 136 | 264 | 392 | 584 | 680 |
Windows | 200 | 328 | 392 | 456 | 712 |
Nøgleindsigt
- Størrelsen af MDF'en var stort set ensartet gennem hele testen, og varierede lidt til sidst (men ikke noget for vanvittigt).
- Timingen for INSERTs var for det meste bedre i Linux, undtagen til sidst, da Windows "vandt runden".
- Størrelsen af transaktionslogfilen blev bedre håndteret i Linux efter hver runde INSERTs.
- Timingen for DELETE'er var for det meste bedre i Linux, undtagen til sidst, hvor Windows "vandt runden" (jeg finder det mærkeligt, at Windows også vandt den sidste INSERT-runde).
- Størrelsen af transaktionslogfilerne efter hver runde af DELETEs var stort set uafgjort med hensyn til op- og nedture mellem de to.
- Jeg ville gerne have prøvet med 100.000 rækker, men jeg manglede lidt diskplads, så jeg begrænsede det til 50.000.
Konklusion
Baseret på resultaterne opnået fra denne test, vil jeg sige, at der ikke er nogen stærk grund til at påstå, at Linux-varianten klarer sig eksponentielt bedre end sin Windows-modstykke. Dette er naturligvis på ingen måde en formel test, som du kan basere dig på for at træffe en sådan beslutning. Selve øvelsen var dog interessant nok for mig.
Jeg vil gætte på, at SQL Server 2019 til Windows nogle gange kommer lidt bagud (ikke meget) på grund af GUI-gengivelsen i baggrunden, hvilket ikke sker i Ubuntu Server-siden af hegnet.
Hvis du er stærkt afhængig af funktioner og muligheder, der er eksklusive for Windows (i det mindste på tidspunktet for dette skrivende), så gå i hvert fald efter det. Ellers vil du næppe træffe et dårligt valg ved at gå efter det ene frem for det andet.