MS SQL Server: RUGSTEUN op steroïede

Wag! Wag! Dit is waar, dit is nie 'n ander artikel oor tipes SQL Server-rugsteun nie. Ek sal nie eers praat oor die verskille tussen herstelmodelle en hoe om 'n oorgroeide hout te hanteer nie.

Miskien (net miskien), nadat jy hierdie pos gelees het, sal jy in staat wees om seker te maak dat die rugsteun wat van jou verwyder word met behulp van standaardmiddels môreaand verwyder sal word, wel, 1.5 keer vinniger. En net as gevolg van die feit dat jy 'n bietjie meer BACKUP DATABASIS parameters gebruik.

As die inhoud van die plasing vir jou duidelik was, is ek jammer. Ek het alles gelees waartoe Google gekom het vir die frase "habr sql server-rugsteun", en in nie een artikel het ek enige melding gevind van die feit dat die rugsteuntyd op een of ander manier met behulp van parameters beïnvloed kan word nie.

Ek sal dadelik u aandag vestig op die opmerking van Alexander Gladchenko (@mssqlhelp):

Moet nooit die BUFFERCOUNT, BLOCKSIZE, MAXTRANSFERSIZE parameters in produksie verander nie. Hulle is slegs gemaak vir die skryf van sulke artikels. In die praktyk sal jy in ’n japtrap van geheueprobleme ontslae raak.

Dit sal natuurlik gaaf wees om die slimste te wees en eksklusiewe inhoud te plaas, maar dit is ongelukkig nie die geval nie. Daar is beide Engelstalige en Russiestalige artikels/plasings (ek is altyd verward oor wat om dit korrek te noem) aan hierdie onderwerp gewy. Hier is 'n paar van die wat ek raakgeloop het: tyd, два, drie (op sql.ru).

So, om mee te begin, sal ek 'n effens gestroopte BACKUP-sintaksis van aanheg MSDN (terloops, ek het hierbo geskryf oor BACKUP DATABASIS, maar dit alles geld vir beide transaksielog-rugsteun en differensiële rugsteun, maar miskien met 'n minder ooglopende effek):

BACKUP DATABASE { database_name | @database_name_var }
  TO <backup_device> [ ,...n ]
  <...>
  [ WITH { <...>
           | <general_WITH_options> [ ,...n ] } ]
[;]

<general_WITH_options> [ ,...n ]::=
<...>
--Media Set Options
 <...>
 | BLOCKSIZE = { blocksize | @blocksize_variable }

--Data Transfer Options
   BUFFERCOUNT = { buffercount | @buffercount_variable }
 | MAXTRANSFERSIZE = { maxtransfersize | @maxtransfersize_variable }
<...>

<…> - dit beteken dat daar iets daar was, maar ek het dit verwyder, want nou is dit nie relevant vir die onderwerp nie.

Hoe neem jy gewoonlik 'n rugsteun? Hoe "leer" hulle hoe om rugsteun te neem in miljarde artikels? Oor die algemeen, as ek 'n eenmalige rugsteun van een of ander nie baie groot databasis moet maak nie, sal ek outomaties iets soos hierdie skryf:

BACKUP DATABASE smth
TO DISK = 'D:Backupsmth.bak'
WITH STATS = 10, CHECKSUM, COMPRESSION, COPY_ONLY;
--ладно, CHECKSUM я написал только чтобы казаться умнее

En oor die algemeen word waarskynlik 75-90% van alle parameters wat gewoonlik in artikels oor rugsteun genoem word, hier gelys. Wel, daar is ook INIT, SKIP. Het jy MSDN besoek? Het jy gesien daar is opsies vir een en 'n halwe skerms? Ek het ook gesien...

U het waarskynlik reeds besef dat ons verder sal praat oor die drie parameters wat in die eerste blok kode gebly het - BLOCKSIZE, BUFFERCOUNT en MAXTRANSFERSIZE. Hier is hul beskrywings van MSDN:

BLOKGROOTTE = { blokgrootte | @ blokgrootte_veranderlike } - dui die fisiese blokgrootte in grepe aan. Ondersteunde groottes is 512, 1024, 2048, 4096, 8192, 16 384, 32 768 en 65 536 grepe (64 KB). Die verstekwaarde is 65 vir bandtoestelle en 536 vir ander toestelle. Tipies is hierdie parameter nie nodig nie omdat die BACKUP-stelling outomaties die toepaslike blokgrootte vir die toestel kies. Deur die blokgrootte te stel, ignoreer die outomatiese blokgrootte seleksie uitdruklik.

BUFFERTELLING = { buffertelling | @ buffertelling_veranderlike } - Definieer die totale aantal I/O-buffers wat vir die rugsteunbewerking gebruik sal word. Jy kan enige positiewe heelgetalwaarde spesifiseer, maar 'n groot aantal buffers kan 'n buite-geheue-fout veroorsaak as gevolg van oormatige virtuele adresspasie in die Sqlservr.exe-proses.

Die totale hoeveelheid spasie wat deur buffers gebruik word, word deur die volgende formule bepaal: BUFFERCOUNT * MAXTRANSFERSIZE.

MAKSOORDRAGGROOTTE = { maksimum oordraggrootte | @ maxtransfersize_variable } spesifiseer die grootste datapakketgrootte, in grepe, om tussen SQL Server en die rugsteunstelmedia uit te ruil. Veelvoude van 65 536 grepe (64 KB) tot 4 194 304 grepe (4 MB) word ondersteun.

Ek sweer – ek het dit al voorheen gelees, maar dit het nooit by my opgekom hoeveel van 'n impak dit op produktiwiteit kan hê nie. Boonop moet ek blykbaar 'n soort "uitkom" maak en erken dat ek selfs nou nog nie heeltemal verstaan ​​wat hulle presies doen nie. Ek moet waarskynlik meer lees oor gebufferde I/O en werk met 'n hardeskyf. Eendag sal ek dit doen, maar vir nou kan ek net 'n skrif skryf wat sal kyk hoe hierdie waardes die spoed waarteen die rugsteun geneem word, beïnvloed.

Ek het 'n klein databasis gemaak, omtrent 10 GB groot, dit op die SSD gesit en die gids vir rugsteun op die HDD gesit.

Ek skep 'n tydelike tabel om die resultate te stoor (ek het dit nie tydelik nie, so ek kan in meer besonderhede in die resultate delf, maar jy besluit self):

DROP TABLE IF EXISTS ##bt_results; 

CREATE TABLE ##bt_results (
    id              int IDENTITY (1, 1) PRIMARY KEY,
    start_date      datetime NOT NULL,
    finish_date     datetime NOT NULL,
    backup_size     bigint NOT NULL,
    compressed_size bigint,
    block_size      int,
    buffer_count    int,
    transfer_size   int
);

Die beginsel van die skrif is eenvoudig - geneste lusse, wat elkeen die waarde van een parameter verander, voeg hierdie parameters in die BACKUP-opdrag in, stoor die laaste rekord met geskiedenis vanaf msdb.dbo.backupset, vee die rugsteunlêer uit en die volgende iterasie . Aangesien die rugsteunuitvoerdata uit die rugsteunstel geneem word, gaan die akkuraatheid ietwat verlore (daar is geen breukdele van sekondes nie), maar ons sal dit oorleef.

Eerstens moet jy xp_cmdshell aktiveer om rugsteun uit te vee (moet dan nie vergeet om dit te deaktiveer as jy dit nie nodig het nie):

EXEC sp_configure 'show advanced options', 1;  
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
EXEC sp_configure 'show advanced options', 0;  
GO

Wel, eintlik:

DECLARE @tmplt AS nvarchar(max) = N'
BACKUP DATABASE [bt]
TO DISK = ''D:SQLServerbackupbt.bak''
WITH 
    COMPRESSION,
    BLOCKSIZE = {bs},
    BUFFERCOUNT = {bc},
    MAXTRANSFERSIZE = {ts}';

DECLARE @sql AS nvarchar(max);

/* BLOCKSIZE values */
DECLARE @bs     int = 4096, 
        @max_bs int = 65536;

/* BUFFERCOUNT values */
DECLARE @bc     int = 7,
        @min_bc int = 7,
        @max_bc int = 800;

/* MAXTRANSFERSIZE values */
DECLARE @ts     int = 524288,   --512KB, default = 1024KB
        @min_ts int = 524288,
        @max_ts int = 4194304;  --4MB

SELECT TOP 1 
    @bs = COALESCE (block_size, 4096), 
    @bc = COALESCE (buffer_count, 7), 
    @ts = COALESCE (transfer_size, 524288)
FROM ##bt_results
ORDER BY id DESC;

WHILE (@bs <= @max_bs)
BEGIN
    WHILE (@bc <= @max_bc)
    BEGIN       
        WHILE (@ts <= @max_ts)
        BEGIN
            SET @sql = REPLACE (REPLACE (REPLACE(@tmplt, N'{bs}', CAST(@bs AS nvarchar(50))), N'{bc}', CAST (@bc AS nvarchar(50))), N'{ts}', CAST (@ts AS nvarchar(50)));

            EXEC (@sql);

            INSERT INTO ##bt_results (start_date, finish_date, backup_size, compressed_size, block_size, buffer_count, transfer_size)
            SELECT TOP 1 backup_start_date, backup_finish_date, backup_size, compressed_backup_size,  @bs, @bc, @ts 
            FROM msdb.dbo.backupset
            ORDER BY backup_set_id DESC;

            EXEC xp_cmdshell 'del "D:SQLServerbackupbt.bak"', no_output;

            SET @ts += @ts;
        END
        
        SET @bc += @bc;
        SET @ts = @min_ts;

        WAITFOR DELAY '00:00:05';
    END

    SET @bs += @bs;
    SET @bc = @min_bc;
    SET @ts = @min_ts;
END

As jy skielik verduideliking nodig het oor wat hier gebeur, skryf in die kommentaar of PM. Vir eers sal ek jou net vertel van die parameters wat ek in BACKUP DATABASIS geplaas het.

Vir BLOCKSIZE het ons 'n "geslote" lys van waardes, en ek het nie 'n rugsteun met BLOCKSIZE < 4KB uitgevoer nie. MAKSOORDRAG enige getal wat 'n veelvoud van 64KB is - van 64KB tot 4MB. Die verstek op my stelsel is 1024KB, ek het 512 - 1024 - 2048 - 4096 geneem.

Dit was moeiliker met BUFFERCOUNT – dit kan enige positiewe getal wees, maar die skakel sê hoe word dit in BACKUP DATABASIS bereken en hoekom is groot waardes gevaarlik?. Dit sê ook hoe om inligting te kry oor met watter BUFFERCOUNT die rugsteun eintlik gemaak is - vir my is dit 7. Dit was geen sin om dit te verminder nie, en die boonste limiet is eksperimenteel ontdek - met BUFFERCOUNT = 896 en MAXTRANSFERSIZE = 4194304 het die rugsteun geval met 'n fout (waaroor in die skakel hierbo geskryf is):

Boodskap 3013, Vlak 16, Staat 1, Lyn 7 RUGSTEUN-DATABASIS eindig abnormaal.

Boodskap 701, Vlak 17, Staat 123, Reël 7 Daar is onvoldoende stelselgeheue in 'verstek' van hulpbronpoel om hierdie navraag uit te voer.

Ter vergelyking sal ek eers die resultate van die uitvoer van 'n rugsteun wys sonder om enige parameters te spesifiseer:

BACKUP DATABASE [bt]
TO DISK = 'D:SQLServerbackupbt.bak'
WITH COMPRESSION;

Wel, rugsteun en rugsteun:

Verwerk 1070072 bladsye vir databasis 'bt', lêer 'bt' op lêer 1.

Verwerk 2 bladsye vir databasis 'bt', lêer 'bt_log' op lêer 1.

RUGSTEUN-DATABASIS het 1070074 bladsye suksesvol in 53.171 sekondes (157.227 MB/sek) verwerk.

Die skrif self, wat die parameters toets, het binne 'n paar uur gewerk, alle metings was in google sigblad. En hier is 'n seleksie van resultate met die drie beste uitvoeringstye (ek het probeer om 'n mooi grafiek te maak, maar in die pos sal ek met 'n tabel moet klaarkom, en in die kommentaar @mengsel hy het bygevoeg baie oulike grafika).

SELECT TOP 7 WITH TIES 
    compressed_size, 
    block_size, 
    buffer_count, 
    transfer_size,
    DATEDIFF(SECOND, start_date, finish_date) AS backup_time_sec
FROM ##bt_results
ORDER BY backup_time_sec ASC;

MS SQL Server: RUGSTEUN op steroïede

Aandag, 'n baie belangrike nota van @mengsel van kommentaar:

Ons kan met vertroue sê dat die verhouding tussen die parameters en rugsteunspoed binne hierdie reekse van waardes ewekansig is, daar is geen patroon nie. Maar wegbeweeg van die ingeboude parameters het natuurlik 'n goeie uitwerking op die resultaat gehad

Dié. Slegs deur die standaard BACKUP-parameters te bestuur, was 'n 2-voudige wins in rugsteunverwyderingtyd: 26 sekondes, teenoor 53 aan die begin. Dit is nie sleg nie, reg? Maar ons moet sien wat gebeur met die herstel. Wat as dit nou 4 keer langer neem om te herstel?

Kom ons meet eers hoe lank dit neem om 'n rugsteun met verstekinstellings te herstel:

RESTORE DATABASE [bt]
FROM DISK = 'D:SQLServerbackupbt.bak'
WITH REPLACE, RECOVERY;

Wel, jy self weet dat, die maniere is daar, vervang is nie vervang nie, herstel is nie herstel nie. En ek doen dit so:

Verwerk 1070072 bladsye vir databasis 'bt', lêer 'bt' op lêer 1.

Verwerk 2 bladsye vir databasis 'bt', lêer 'bt_log' op lêer 1.

HERSTEL DATABASIS het 1070074 bladsye suksesvol verwerk in 40.752 sekondes (205.141 MB/sek).

Nou sal ek probeer om rugsteun wat geneem is met veranderde BLOCKSIZE, BUFFERCOUNT en MAXTRANSFERSIZE te herstel.

BLOCKSIZE = 16384, BUFFERCOUNT = 224, MAXTRANSFERSIZE = 4194304

HERSTEL DATABASIS het 1070074 bladsye suksesvol verwerk in 32.283 sekondes (258.958 MB/sek).

BLOCKSIZE = 4096, BUFFERCOUNT = 448, MAXTRANSFERSIZE = 4194304

HERSTEL DATABASIS het 1070074 bladsye suksesvol verwerk in 32.682 sekondes (255.796 MB/sek).

BLOCKSIZE = 16384, BUFFERCOUNT = 448, MAXTRANSFERSIZE = 2097152

HERSTEL DATABASIS het 1070074 bladsye suksesvol verwerk in 32.091 sekondes (260.507 MB/sek).

BLOCKSIZE = 4096, BUFFERCOUNT = 56, MAXTRANSFERSIZE = 4194304

HERSTEL DATABASIS het 1070074 bladsye suksesvol verwerk in 32.401 sekondes (258.015 MB/sek).

Die RESTORE DATABASE-stelling verander nie tydens herstel nie; hierdie parameters word nie daarin gespesifiseer nie; SQL Server bepaal dit self vanaf die rugsteun. En dit is duidelik dat daar selfs met herstel 'n wins kan wees - amper 20% vinniger (Om eerlik te wees, ek het nie veel tyd aan herstel bestee nie, ek het deur verskeie van die "vinnigste" rugsteune gehardloop en seker gemaak dat daar geen agteruitgang was nie).

Net vir ingeval, laat ek verduidelik dat dit nie 'n paar parameters is wat vir almal optimaal is nie. U kan slegs die optimale parameters vir uself kry deur te toets. Ek het hierdie resultate gekry, jy sal verskillende kry. Maar jy sien dat jy jou rugsteun kan "instel" en hulle kan eintlik vinniger vorm en ontplooi.

Ek beveel ook sterk aan dat jy die dokumentasie in sy geheel lees, want daar kan nuanses spesifiek vir jou stelsel wees.

Sedert ek oor rugsteun begin skryf het, wil ek dadelik oor nog een "optimering" skryf, wat meer algemeen is as "tuning"-parameters (sover ek verstaan, word dit deur ten minste sommige rugsteunhulpprogramme gebruik, miskien saam met die parameters vroeër beskryf), maar dit is ook nog nie op Habré beskryf nie.

As ons na die tweede reël in die dokumentasie kyk, reg onder BACKUP DATABASIS, daar sien ons:

TO <backup_device> [ ,...n ]

Wat dink jy sal gebeur as jy verskeie rugsteuntoestelle spesifiseer? Die sintaksis laat dit toe. En 'n baie interessante ding sal gebeur - die rugsteun sal eenvoudig oor verskeie toestelle "verspreid" word. Dié. elke "toestel" individueel sal nutteloos wees, een verloor, die hele rugsteun verloor. Maar hoe sal sulke smeer rugsteunspoed beïnvloed?

Kom ons probeer om 'n rugsteun te maak op twee "toestelle" wat langs mekaar in dieselfde vouer geleë is:

BACKUP DATABASE [bt]
TO 
    DISK = 'D:SQLServerbackupbt1.bak',
    DISK = 'D:SQLServerbackupbt2.bak'   
WITH COMPRESSION;

Vaders van die wêreld, hoekom word dit gedoen?

Verwerk 1070072 bladsye vir databasis 'bt', lêer 'bt' op lêer 1.

Verwerk 2 bladsye vir databasis 'bt', lêer 'bt'log' op lêer 1.

RUGSTEUN-DATABASIS het 1070074 bladsye suksesvol in 40.092 sekondes (208.519 MB/sek) verwerk.

Het die rugsteun sommer uit die bloute 25% vinniger geword? Wat as ons nog 'n paar toestelle byvoeg?

BACKUP DATABASE [bt]
TO 
    DISK = 'D:SQLServerbackupbt1.bak',
    DISK = 'D:SQLServerbackupbt2.bak',
    DISK = 'D:SQLServerbackupbt3.bak',
    DISK = 'D:SQLServerbackupbt4.bak'
WITH COMPRESSION;

RUGSTEUN-DATABASIS het 1070074 bladsye suksesvol in 34.234 sekondes (244.200 MB/sek) verwerk.

In totaal is die wins ongeveer 35% van die tyd van die neem van 'n rugsteun slegs as gevolg van die feit dat die rugsteun op een slag na 4 lêers op een skyf geskryf word. Ek het 'n groter getal nagegaan - daar is geen wins op my skootrekenaar nie, optimaal - 4 toestelle. Vir jou - ek weet nie, jy moet kyk. Wel, terloops, as jy hierdie toestelle het - dit is regtig verskillende skywe, baie geluk, die wins behoort selfs meer betekenisvol te wees.

Kom ons praat nou oor hoe om hierdie geluk te herstel. Om dit te doen, moet u die herstelopdrag verander en alle toestelle lys:

RESTORE DATABASE [bt]
FROM 
    DISK = 'D:SQLServerbackupbt1.bak',
    DISK = 'D:SQLServerbackupbt2.bak',
    DISK = 'D:SQLServerbackupbt3.bak',
    DISK = 'D:SQLServerbackupbt4.bak'
WITH REPLACE, RECOVERY;

HERSTEL DATABASIS het 1070074 bladsye suksesvol verwerk in 38.027 sekondes (219.842 MB/sek).

'n Bietjie vinniger, maar iewers naby, nie betekenisvol nie. Oor die algemeen word die rugsteun vinniger verwyder en op dieselfde manier herstel - sukses? Wat my betref, is dit nogal 'n sukses. Hierdie is belangrik, so ek herhaal - as jy as jy ten minste een van hierdie lêers verloor, verloor jy die hele rugsteun.

As jy in die log kyk na die rugsteuninligting wat met Trace Flags 3213 en 3605 vertoon word, sal jy sien dat wanneer jy na verskeie toestelle rugsteun, die aantal BUFFERCOUNT ten minste toeneem. Waarskynlik kan jy probeer om meer optimale parameters vir BUFFERCOUNT, BLOCKSIZE, MAXTRANSFERSIZE te kies, maar ek het nie dadelik daarin geslaag nie, en ek was te lui om weer sulke toetse uit te voer, maar vir 'n ander aantal lêers. En dis jammer vir die wiele. As jy sulke toetse by die huis wil organiseer, is dit nie moeilik om die draaiboek oor te maak nie.

Laastens, kom ons praat oor prys. As die rugsteun parallel met die gebruikers se werk verwyder word, moet u 'n baie verantwoordelike benadering tot toetsing volg, want as die rugsteun vinniger verwyder word, word die skywe meer gespanne, die las op die verwerker neem toe (jy moet nog saampers dit op die vlieg), en dienooreenkomstig neem die algehele reaksie van die stelsel af.

Ek grap net, maar ek verstaan ​​goed dat ek geen onthullings gemaak het nie. Wat hierbo geskryf is, is bloot 'n demonstrasie van hoe jy die optimale parameters vir die neem van rugsteun kan kies.

Onthou dat alles wat jy doen op jou eie risiko en risiko gedoen word. Gaan jou rugsteun na en moenie vergeet van DBCC CHECKDB nie.

Bron: will.com

Voeg 'n opmerking