MS SQL Server: BACKUP li ser steroids

Payin! Payin! Rast e, ev ne gotarek din e di derheqê celebên paşvekêşana SQL Server de. Ez ê li ser cûdahiyên di navbera modelên başbûnê de û meriv çawa bi têketinek zêde mezin re mijûl bibim nebêjim.

Dibe ku (tenê belkî), piştî xwendina vê postê, hûn ê karibin pê ewle bin ku paşgira ku bi karanîna rêgezên standard ji we tê rakirin dê sibê êvarê, baş, 1.5 carî zûtir were rakirin. Û tenê ji ber vê rastiyê ku hûn pîvanên BACKUP DATABASE hinekî bêtir bikar tînin.

Ger naveroka postê ji we re eşkere bû, ez xemgîn im. Min her tiştê ku Google ji bo peyva "vegerandina servera habr sql" girt xwend, û di yek gotarekê de min behsa vê yekê nedît ku dema paşvekişandinê dikare bi rengek bi karanîna parameteran were bandor kirin.

Ez ê tavilê bala we bikişînim ser şîroveya Alexander Gladchenko (@mssqlhelp):

Di hilberînê de ti carî pîvanên BUFFERCOUNT, BLOCKSIZE, MAXTRANSFERSIZE neguherînin. Ew tenê ji bo nivîsandina gotarên weha têne çêkirin. Di pratîkê de, hûn ê di demek kurt de ji pirsgirêkên bîranînê xilas bibin.

Bê guman, ew ê xweş be ku meriv bibe ya herî jîr û naveroka taybetî biweşîne, lê, mixabin, ne wusa ye. Hem gotar/mesajên bi zimanê îngilîzî û hem jî bi zimanê rûsî (ez her gav şaş dimînim ka ez ê ji wan re rast bi nav bikim) ji vê mijarê re hatine veqetandin. Li vir hinek ji yên ku ez pê re hatim hene: carinan, два, sê (li ser sql.ru).

Ji ber vê yekê, ji bo destpêkê, ez ê hevoksaziyek BACKUP-ê ya piçekî jêkirî pêve bikim MSDN (bi awayê, min li jor li ser BACKUP DATABASE nivîsî, lê ev hemî hem ji bo paşvekêşana danûstendina danûstendinê û hem jî ji paşvekêşana cûda re derbas dibe, lê dibe ku bi bandorek kêmtir eşkere):

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 }
<...>

<…> - ev tê wê wateyê ku tiştek li wir hebû, lê min ew jê kir ji ber ku naha ew bi mijarê re ne têkildar e.

Hûn bi gelemperî çawa paşvekişandinê digirin? Ew çawa "hîn dikin" ka meriv çawa di mîlyaran gotaran de paşvekêşan digire? Bi gelemperî, ger hewce bike ku ez ji hin databasên ne pir mezin vegerek yek carî çê bikim, ez ê bixweber tiştek weha binivîsim:

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

Û, bi gelemperî, belkî 75-90% ji hemî pîvanên ku bi gelemperî di gotarên di derheqê paşkêşan de têne destnîşan kirin li vir têne navnîş kirin. Welê, INIT, SKIP jî heye. We serdana MSDN kir? We dît ku vebijarkên yek û nîv ekranan hene? Min jî dît...

Dibe ku we jixwe fêm kir ku bêtir em ê li ser sê pîvanên ku di bloka yekem a kodê de mane biaxivin - BLOCKSIZE, BUFFERCOUNT û MAXTRANSFERSIZE. Li vir şiroveyên wan ji MSDN hene:

BLOCKSIZE = { blocksize | @ blocksize_variable } - mezinahiya bloka fizîkî bi byte nîşan dide. Mezinahiyên têne piştgirî kirin 512, 1024, 2048, 4096, 8192, 16, 384, û 32 bytes (768 KB) ne. Nirxa xwerû ji bo cîhazên tape 65 û ji bo amûrên din 536 e. Bi gelemperî ev pîvan ne hewce ye ji ber ku daxuyaniya BACKUP bixweber mezinahiya blokê ya guncan ji bo cîhazê hildibijêre. Sazkirina mezinahiya blokê bi eşkereyî hilbijartina mezinahiya blokê ya otomatîkî ji holê radike.

BUFFERCOUNT = { buffercount | @ buffercount_variable } - Jimara giştî ya tamponên I/O yên ku dê ji bo xebata hilanînê werin bikar anîn destnîşan dike. Hûn dikarin her nirxek bêkêmasî ya erênî diyar bikin, lê hejmareke mezin a tampon dibe ku bibe sedema xeletiyek ji bîrê ji ber zêde cîhê navnîşana virtual di pêvajoya Sqlservr.exe de.

Tevahiya cîhê ku ji hêla tamponan ve hatî bikar anîn bi formula jêrîn tête destnîşankirin: BUFFERCOUNT * MAXTRANSFERSIZE.

MAXTRANSFERSIZE = { maxtransfersize | @ maxtransfersize_variable } mezinahiya pakêta daneyê ya herî mezin, di byteyan de, diyar dike ku di navbera SQL Server û medyaya set hilanînê de biguhezîne. Gelek ji 65 bytes (536 KB) heta 64 bytes (4 MB) têne piştgirî kirin.

Ez sond dixwim - min berê jî ev yek xwendibû, lê qet nedihat bîra min ku ew dikarin çiqas bandorek li ser hilberînê bikin. Wekî din, xuya ye, pêdivî ye ku ez celebek "derketinê" bikim û bipejirînim ku heya niha jî ez bi tevahî fam nakim ka ew bi rastî çi dikin. Dibe ku ez hewce bikim ku di derbarê I/O-ya tamponkirî û xebata bi ajokerek hişk de bêtir bixwînim. Rojekê ez ê wiya bikim, lê ji bo naha ez dikarim tenê skrîptek binivîsim ku dê kontrol bike ka van nirxan çawa bandorê li leza hilgirtina hilanînê dikin.

Min danegehek piçûk çêkir, bi qasî 10 GB mezin, ew danî ser SSD-ê, û pelrêça ji bo paşvekişandinê li ser HDD-ê danî.

Ez tabloyek demkî diafirînim da ku encaman hilîne (min ew demkî nîn e, ji ber vê yekê ez dikarim encaman bi hûrgulî bikolim, lê hûn bi xwe biryar didin):

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
);

Prensîba skrîptê hêsan e - xelekên hêlîn, ku her yek ji wan nirxa yek parametreyê diguhezîne, van parameteran têxe fermana BACKUP, tomara paşîn a bi dîrokê re ji msdb.dbo.backupset hilîne, pelê hilanînê jêbirin û dubareya din . Ji ber ku daneyên darvekirina paşvekişandinê ji hilanînê tê girtin, rastbûn hinekî winda dibe (parçeyên çirkeyan tune), lê em ê ji vê yekê sax bimînin.

Pêşî hûn hewce ne ku xp_cmdshell çalak bikin da ku paşkêşan jêbirin (paşê ji bîr nekin ku hûn jê re ne hewce neçalak bikin):

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

Belê, bi rastî:

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

Heke hûn ji nişkê ve hewceyê zelalkirinê li ser tiştê ku li vir diqewime, di şîroveyan an PM-ê de binivîsin. Heya nuha, ez ê tenê li ser pîvanên ku min di BACKUP DATABASE de danîne ji we re vebêjim.

Ji bo BLOCKSIZE navnîşek nirxa me ya "girtî" heye, û min bi BLOCKSIZE < 4KB vegerek nekiriye. Her hejmarê ku pirjimara 64KB-yê ye - ji 64KB heya 4MB-ê MAXTRANSFERSIZE. Vebijêrk li ser pergala min 1024KB ye, min 512 - 1024 - 2048 - 4096 girt.

Bi BUFFERCOUNT re dijwartir bû - ew dikare her hejmarek erênî be, lê girêdan dibêje ew di BACKUP DATABASE de çawa tê hesibandin û çima nirxên mezin xeternak in?. Di heman demê de dibêje meriv çawa agahdariya li ser kîjan BUFFERCOUNT hilanînê bi rastî hatî çêkirin - ji bo min ew 7 e. Ti wateya kêmkirina wê tune bû, û sînorê jorîn bi ceribandinê hate kifş kirin - bi BUFFERCOUNT = 896 û MAXTRANSFERSIZE = 4194304 paşvekişandin bi xeletiyek (li ser ku di girêdana jorîn de hatî nivîsandin):

Msg 3013, Asta 16, Dewlet 1, Rêz 7 BAZANA BERXWEDANA DANGEHA bi rengek ne normal diqede.

Msg 701, Asta 17, Dewlet 123, Rêz 7 Di hewza çavkaniyê ya 'default' de bîranîna pergalê têrê nake ku vê pirsê bimeşîne.

Ji bo berhevdanê, ez ê pêşî encamên xebitandina hilanînê nîşan bidim bêyî ku bi tevahî parameteran diyar bikim:

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

Welê, hilanînê û hilanînê:

1070072 rûpel ji bo databasa 'bt', pelê 'bt' li ser pelê 1.

2 rûpel ji bo databasa 'bt', pelê 'bt_log' li ser pelê 1.

BACKUP DATABASE 1070074 rûpel di 53.171 çirkeyan de (157.227 MB/sîk) bi serkeftî pêvajo kir.

Nivîsar bixwe, ceribandina pîvanan, di nav çend demjimêran de xebitî, hemî pîvandin tê de bûn google spreadsheet. Û li vir hilbijarkek encaman bi sê demên darvekirinê yên çêtirîn heye (min hewl da ku grafiyek xweş çêkim, lê di postê de ez ê neçar bim ku bi tabloyek, û di şîroveyan de têbikoşim @mixsture lê zêde kirin grafikên pir xweş).

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: BACKUP li ser steroids

Bala xwe, notek pir girîng ji @mixsture ji şîrove:

Em dikarin bi pêbawerî bibêjin ku têkiliya di navbera pîvan û leza paşvekişandinê de di nav van rêzikên nirxan de random e, nexşeyek tune. Lê dûrketina ji pîvanên çêkirî eşkere bandorek baş li ser encamê kir

Ewan. Tenê bi rêvebirina pîvanên BACKUP-ê yên standard di dema rakirina hilanînê de 2-car qezencek bû: 26 saniye, li hember 53 di destpêkê de. Ew ne xirab e, rast? Lê divê em bibînin ka bi restorasyonê çi dibe. Ger ew niha 4 carî dirêjtir ji nûvekirinê bigire?

Pêşîn, em bipîvin ka çiqas dem digire da ku hilanînê bi mîhengên xwerû vegerîne:

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

Welê, hûn bi xwe jî dizanin ku, rê hene, veguheztin nayê veguheztin, başbûn ne başbûn e. Û ez bi vî awayî dikim:

1070072 rûpel ji bo databasa 'bt', pelê 'bt' li ser pelê 1.

2 rûpel ji bo databasa 'bt', pelê 'bt_log' li ser pelê 1.

RESTORE DATABASE 1070074 rûpel di 40.752 çirkeyan de (205.141 MB/sîk) bi serkeftî pêvajo kir.

Naha ez ê hewl bidim ku paşkêşên ku bi BLOCKSIZE, BUFFERCOUNT û MAXTRANSFERSIZE-ya guhertî hatine girtin vegerînim.

BLOCKSIZE = 16384, BUFFERCOUNT = 224, MAXTRANSFERSIZE = 4194304

RESTORE DATABASE 1070074 rûpel di 32.283 çirkeyan de (258.958 MB/sîk) bi serkeftî pêvajo kir.

BLOCKSIZE = 4096, BUFFERCOUNT = 448, MAXTRANSFERSIZE = 4194304

RESTORE DATABASE 1070074 rûpel di 32.682 çirkeyan de (255.796 MB/sîk) bi serkeftî pêvajo kir.

BLOCKSIZE = 16384, BUFFERCOUNT = 448, MAXTRANSFERSIZE = 2097152

RESTORE DATABASE 1070074 rûpel di 32.091 çirkeyan de (260.507 MB/sîk) bi serkeftî pêvajo kir.

BLOCKSIZE = 4096, BUFFERCOUNT = 56, MAXTRANSFERSIZE = 4194304

RESTORE DATABASE 1070074 rûpel di 32.401 çirkeyan de (258.015 MB/sîk) bi serkeftî pêvajo kir.

Daxuyaniya RESTORE DATABASE di dema hilanînê de nayê guheztin; ev pîvan di wê de nehatine diyar kirin; SQL Server bixwe wan ji hilanînê destnîşan dike. Û diyar e ku tewra bi başbûnê re jî dibe ku qezencek hebe - hema hema 20% zûtir (Bi rastî, min pir dem li ser başbûnê xerc nekir, min çend paşpirtikên "zûtirîn" derbas kir û piştrast kir ku xirabûnek tune).

Tenê di rewşê de, bila ez zelal bikim ku ev ne hin parametreyên ku ji bo her kesî çêtirîn in. Hûn dikarin tenê bi ceribandinê pîvanên çêtirîn ji bo xwe bistînin. Min ev encam girt, hûn ê yên cûda bistînin. Lê hûn dibînin ku hûn dikarin paşpirtikên xwe "aheng" bikin û ew bi rastî dikarin zûtir çêbibin û bicîh bikin.

Di heman demê de ez bi tundî pêşniyar dikim ku hûn belgeyê bi tevahî bixwînin, ji ber ku dibe ku nuwazeyên taybetî yên pergala we hebin.

Ji ber ku min dest bi nivîsandina paşgiran kir, ez dixwazim tavilê li ser yek "optimîzasyonek" din binivîsim, ku ji pîvanên "tuning" gelemperîtir e (bi qasî ku ez fêm dikim, ew ji hêla kêmasî ve hin karûbarên paşvekêşanê ve tê bikar anîn, dibe ku digel pîvanan berê hatî diyar kirin), lê hîn li ser Habré jî nehatiye vegotin.

Ger em li rêzika duyemîn a di belgeyê de, rast di bin BACKUP DATABASE de, binêrin, li wir em dibînin:

TO <backup_device> [ ,...n ]

Ma hûn difikirin ku dê çi bibe ger hûn çend amûrên hilanînê_device diyar bikin? Syntax destûrê dide. Û tiştek pir balkêş dê biqewime - hilanînê dê tenê li çend cîhazan "belav bibe". Ewan. her "cîhaz" bi serê xwe dê bêkêr be, yek wenda bike, tevahiya paşvekişandinê winda bike. Lê dê çawa şilkirinek wusa bandorê li leza hilanînê bike?

Ka em hewl bidin ku li ser du "cîhazên" ku li kêleka hev di heman peldankê de ne paşvekêşek çêbikin:

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

Bavê dinyayê, çima ev yek tê kirin?

1070072 rûpel ji bo databasa 'bt', pelê 'bt' li ser pelê 1.

Ji bo databasa 'bt', pelê 'bt' 2 rûpel hatin pêvajo kirintêketin' li ser pelê 1.

BACKUP DATABASE 1070074 rûpel di 40.092 çirkeyan de (208.519 MB/sîk) bi serkeftî pêvajo kir.

Ma paşvekişandin ji sedî 25 zûtir bû? Ger em çend cîhazên din lê zêde bikin?

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

BACKUP DATABASE 1070074 rûpel di 34.234 çirkeyan de (244.200 MB/sîk) bi serkeftî pêvajo kir.

Bi tevahî, qezenc nêzî 35% ji dema hilanînê ye tenê ji ber vê yekê ku hilanînê bi yekcarê li ser 4 pelan li ser yek dîskê tê nivîsandin. Min hejmareke mezintir kontrol kir - li ser laptopa min qezencek tune, herî baş - 4 cîhaz. Ji bo we - ez nizanim, hûn hewce ne ku kontrol bikin. Welê, bi awayê, heke we van amûran hebin - ev bi rastî dîskên cihêreng in, pîrozbahî ne, divê qezenc hîn girîngtir be.

Niha emê bipeyivin ka meriv çawa vê bextewariyê vedigire. Ji bo vê yekê, hûn ê neçar bin ku emrê vegerandinê biguhezînin û hemî cîhazan navnîş bikin:

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

RESTORE DATABASE 1070074 rûpel di 38.027 çirkeyan de (219.842 MB/sîk) bi serkeftî pêvajo kir.

Piçek zûtir, lê li cîhek nêzîk, ne girîng e. Bi gelemperî, paşvekişandin zûtir tê rakirin, lê bi heman rengî tê nûve kirin - serkeftin? Ji bo min, ew pir serketî ye. Ev girîng e, ji ber vê yekê ez dubare dikim - heke hûn heke hûn bi kêmanî yek ji van pelan winda bikin, hûn hemî hilanînê winda dikin.

Ger hûn di têketinê de li agahdariya paşvekêşanê ya ku bi karanîna Trace Flags 3213 û 3605 têne xuyang kirin binihêrin, hûn ê bibînin ku dema ku pişta xwe ji çend cîhazan re digirin, bi kêmî ve hejmara BUFFERCOUNT zêde dibe. Belkî, hûn dikarin hewl bidin ku ji bo BUFFERCOUNT, BLOCKSIZE, MAXTRANSFERSIZE parametreyên çêtirîn hilbijêrin, lê ez tavilê bi ser neketim, û ez pir tembel bûm ku ez dîsa ceribandinek weha bikim, lê ji bo hejmarek cûda pelan. Û ji bo tekeran şerm e. Ger hûn dixwazin ceribandinek wusa li malê organîze bikin, ji nû ve çêkirina senaryoyê ne dijwar e.

Di dawiyê de, em li ser bihayê biaxivin. Ger hilanînê bi xebata bikarhêneran re paralel were rakirin, hûn hewce ne ku ji ceribandinê re nêzîkatiyek pir berpirsiyar bavêjin, ji ber ku heke paşvekişandin zûtir were rakirin, dîsk bêtir teng dibin, barkirina li ser pêvajoyê zêde dibe (hûn hîn jî pêdivî ye ku hûn bişkînin ew di firînê de ye), û li gorî vê yekê, bersivdana giştî ya pergalê kêm dibe.

Tenê henekê xwe dikim, lê ez baş fam dikim ku min ti eşkere nekir. Tiştê ku li jor hatî nivîsandin tenê xwenîşandanek e ku hûn çawa dikarin ji bo girtina paşkêşan pîvanên çêtirîn hilbijêrin.

Bînin bîra xwe ku her tiştê ku hûn dikin bi xeter û xetera we tê kirin. Piştgirên xwe kontrol bikin û DBCC CHECKDB ji bîr nekin.

Source: www.habr.com

Add a comment