Metoda e poke shkencore, ose si të zgjidhni një konfigurim të bazës së të dhënave duke përdorur standarde dhe një algoritëm optimizimi

Përshëndetje

Vendosa të ndaj gjetjen time - frytin e mendimit, provës dhe gabimit.
Në përgjithësi: kjo nuk është një gjetje, natyrisht - e gjithë kjo duhet të ishte e njohur për një kohë të gjatë, për ata që janë të përfshirë në përpunimin e aplikuar të të dhënave statistikore dhe optimizimin e çdo sistemi, jo domosdoshmërisht specifikisht DBMS.
Dhe: po, ata e dinë, ata shkruajnë artikuj interesantë për kërkimin e tyre, shembull (UPD.: në komente ata vunë në dukje një projekt shumë interesant: ndryshe )
Nga ana tjetër: në mënyrë të rastësishme nuk shoh ndonjë përmendje apo përhapje të gjerë të kësaj qasjeje në internet midis specialistëve të IT, DBA.

Pra, deri në pikën.

Le të supozojmë se kemi një detyrë: të vendosim një sistem të caktuar shërbimi për të shërbyer një lloj pune.

Për këtë punë dihet: çfarë është, si matet cilësia e kësaj vepre dhe cili është kriteri për matjen e kësaj cilësie.

Le të supozojmë gjithashtu se dihet pak a shumë dhe kuptohet: saktësisht se si kryhet puna në (ose me) këtë sistem shërbimi.

"Pak a shumë" - kjo do të thotë që është e mundur të përgatitet (ose të merret nga diku) një mjet, shërbim, shërbim i caktuar që mund të sintetizohet dhe aplikohet në sistem me një ngarkesë provë mjaftueshëm të përshtatshme për atë që do të jetë në prodhim, në kushte mjaftueshëm të përshtatshme për të punuar në prodhim .

Epo, le të supozojmë se dihet një grup parametrash rregullimi për këtë sistem shërbimi, të cilat mund të përdoren për të konfiguruar këtë sistem për sa i përket produktivitetit të punës së tij.

Dhe cili është problemi - nuk ka një kuptim mjaftueshëm të plotë të këtij sistemi shërbimi, ai që ju lejon të konfiguroni me profesionalizëm cilësimet e këtij sistemi për ngarkesën e ardhshme në një platformë të caktuar dhe të merrni produktivitetin e kërkuar të sistemit.

Epo. Ky është pothuajse gjithmonë rasti.

Çfarë mund të bëni këtu?

Epo, gjëja e parë që ju vjen në mendje është të shikoni dokumentacionin për këtë sistem. Kuptoni se cilat janë diapazoni i pranueshëm për vlerat e parametrave të rregullimit. Dhe, për shembull, duke përdorur metodën e zbritjes së koordinatave, zgjidhni vlerat për parametrat e sistemit në teste.

Ato. jepni sistemit një lloj konfigurimi, në formën e një grupi specifik vlerash për parametrat e tij të konfigurimit.

Aplikoni një ngarkesë provë në të, duke përdorur pikërisht këtë mjet-vegël gjenerator të ngarkesës.
Dhe shikoni vlerën - përgjigjen, ose një metrikë të cilësisë së sistemit.

Mendimi i dytë mund të jetë përfundimi se kjo është një kohë shumë e gjatë.

Epo, kjo do të thotë: nëse ka shumë parametra cilësorë, nëse diapazoni i vlerave të tyre që ekzekutohen janë të mëdha, nëse çdo test individual i ngarkesës kërkon shumë kohë për t'u përfunduar, atëherë: po, e gjithë kjo mund të marrë një kohë të papranueshme kohe e gjate.

Epo, ja çfarë mund të kuptoni dhe mbani mend.

Mund të zbuloni se në grupin e vlerave të parametrave të cilësimeve të sistemit të shërbimit ekziston një vektor, si një sekuencë e disa vlerave.

Çdo vektor i tillë, duke qenë gjëra të tjera të barabarta (në faktin se nuk ndikohet nga ky vektor), korrespondon me një vlerë plotësisht të caktuar të metrikës - një tregues i cilësisë së funksionimit të sistemit, nën një ngarkesë testimi.

dmth

Le të shënojmë vektorin e konfigurimit të sistemit si Metoda e poke shkencore, ose si të zgjidhni një konfigurim të bazës së të dhënave duke përdorur standarde dhe një algoritëm optimizimiKu Metoda e poke shkencore, ose si të zgjidhni një konfigurim të bazës së të dhënave duke përdorur standarde dhe një algoritëm optimizimi; Ku Metoda e poke shkencore, ose si të zgjidhni një konfigurim të bazës së të dhënave duke përdorur standarde dhe një algoritëm optimizimi — numri i parametrave të konfigurimit të sistemit, sa prej këtyre parametrave ka.

Dhe vlera e metrikës që korrespondon me këtë Metoda e poke shkencore, ose si të zgjidhni një konfigurim të bazës së të dhënave duke përdorur standarde dhe një algoritëm optimizimi le ta shënojmë si
Metoda e poke shkencore, ose si të zgjidhni një konfigurim të bazës së të dhënave duke përdorur standarde dhe një algoritëm optimizimi, atëherë marrim një funksion: Metoda e poke shkencore, ose si të zgjidhni një konfigurim të bazës së të dhënave duke përdorur standarde dhe një algoritëm optimizimi

Epo, atëherë: gjithçka zbret menjëherë, në rastin tim: pothuajse të harruara nga ditët e mia studentore, algoritme për kërkimin e ekstremit të një funksioni.

Mirë, por këtu lind një pyetje organizative dhe e aplikuar: cili algoritëm të përdoret.

  1. Në kuptimin - në mënyrë që të mund të kodoni më pak me dorë.
  2. Dhe që ajo të funksionojë, d.m.th. gjeti ekstremin (nëse ka), mirë, të paktën më shpejt se zbritja koordinative.

Pika e parë lë të kuptohet se ne duhet të shikojmë drejt disa mjediseve në të cilat algoritme të tilla tashmë janë zbatuar dhe, në një farë forme, janë gati për përdorim në kod.
Epo, e di python и cran-r

Pika e dytë do të thotë që ju duhet të lexoni për vetë algoritmet, cilat janë ato, cilat janë kërkesat e tyre, veçoritë e punës së tyre.

Dhe ajo që ata japin mund të jenë efekte anësore të dobishme - rezultate, ose drejtpërdrejt nga vetë algoritmi.

Ose ato mund të merren nga rezultatet e algoritmit.

Shumë varet nga kushtet e hyrjes.

Për shembull, nëse, për ndonjë arsye, ju duhet të merrni një rezultat më shpejt, mirë, duhet të shikoni drejt algoritmeve të zbritjes së gradientit dhe të zgjidhni një prej tyre.

Ose, nëse koha nuk është aq e rëndësishme, mund të përdorni, për shembull, metodat e optimizimit stokastik, siç është një algoritëm gjenetik.

Unë propozoj të shqyrtojmë punën e kësaj qasjeje, duke zgjedhur konfigurimin e sistemit, duke përdorur një algoritëm gjenetik, në tjetrën, si të thuash: punën laboratorike.

Origjinali:

  1. Le të ketë, si një sistem shërbimi: oracle xe 18c
  2. Lëreni t'i shërbejë aktivitetit transaksional dhe qëllimit: të përftohet xhiroja më e lartë e mundshme e nënbazës së të dhënave, në transaksione/sek.
  3. Transaksionet mund të jenë shumë të ndryshme në natyrën e punës me të dhënat dhe kontekstin e punës.
    Le të biem dakord që këto janë transaksione që nuk përpunojnë një sasi të madhe të të dhënave tabelare.
    Në kuptimin që ata nuk gjenerojnë më shumë të dhëna zhbërje sesa ribërje dhe nuk përpunojnë përqindje të mëdha rreshtash dhe tabelash të mëdha.

Këto janë transaksione që ndryshojnë një rresht në një tabelë pak a shumë të madhe, me një numër të vogël indeksesh në këtë tabelë.

Në këtë situatë: produktiviteti i nënbazës së të dhënave për përpunimin e transaksioneve, me një rezervë, do të përcaktohet nga cilësia e përpunimit nga databaza redoks.

Mohim përgjegjësie - nëse flasim posaçërisht për cilësimet e subdb.

Sepse, në rastin e përgjithshëm, mund të ketë, për shembull, bllokime transaksionale midis sesioneve SQL, për shkak të dizajnit të punës së përdoruesit me të dhënat tabelare dhe/ose modelin tabelor.

E cila, natyrisht, do të ketë një efekt dëshpërues në metrikën TPS dhe ky do të jetë një faktor ekzogjen, në lidhje me nënbazën e të dhënave: mirë, kështu është projektuar modeli tabelor dhe puna me të dhënat në të që ndodhin bllokime.

Prandaj, për pastërtinë e eksperimentit, ne do ta përjashtojmë këtë faktor, dhe më poshtë do të sqaroj saktësisht se si.

  1. Le të supozojmë, për saktësi, se 100% e komandave SQL të paraqitura në bazën e të dhënave janë komanda DML.
    Lërini karakteristikat e punës së përdoruesit me nënbazën e të dhënave të jenë të njëjta në teste.
    Gjegjësisht: numri i seancave skl, të dhënat tabelare, si funksionojnë seancat skl me to.
  2. Subd punon në FORCE LOGGING, ARCHIVELOG modalitetet. Modaliteti i bazës së të dhënave të rikthimit është çaktivizuar, në nivelin nënd.
  3. Redo logs: ndodhet në një sistem skedar të veçantë, në një "disk" të veçantë;
    Pjesa tjetër e komponentit fizik të bazës së të dhënave: në një sistem skedar tjetër, të veçantë, në një "disk" të veçantë:

Më shumë detaje rreth pajisjes fizike. komponentët e bazës së të dhënave laboratorike

SQL> select status||' '||name from v$controlfile;
 /db/u14/oradata/XE/control01.ctl
SQL> select GROUP#||' '||MEMBER from v$logfile;
1 /db/u02/oradata/XE/redo01_01.log
2 /db/u02/oradata/XE/redo02_01.log
SQL> select FILE_ID||' '||TABLESPACE_NAME||' '||round(BYTES/1024/1024,2)||' '||FILE_NAME as col from dba_data_files;
4 UNDOTBS1 2208 /db/u14/oradata/XE/undotbs1_01.dbf
2 SLOB 128 /db/u14/oradata/XE/slob01.dbf
7 USERS 5 /db/u14/oradata/XE/users01.dbf
1 SYSTEM 860 /db/u14/oradata/XE/system01.dbf
3 SYSAUX 550 /db/u14/oradata/XE/sysaux01.dbf
5 MONITOR 128 /db/u14/oradata/XE/monitor.dbf
SQL> !cat /proc/mounts | egrep "/db/u[0-2]"
/dev/vda1 /db/u14 ext4 rw,noatime,nodiratime,data=ordered 0 0
/dev/mapper/vgsys-ora_redo /db/u02 xfs rw,noatime,nodiratime,attr2,nobarrier,inode64,logbsize=256k,noquota 0 0

Fillimisht, në këto kushte ngarkese, doja të përdorja transaksionin subd SLOB-dobi
Ka një veçori kaq të mrekullueshme, do të citoj autorin:

Në zemër të SLOB është "metoda SLOB". Metoda SLOB synon të testojë platformat
pa grindje për aplikim. Nuk mund të arrihet performanca maksimale e harduerit
duke përdorur kodin e aplikacionit që është, për shembull, i lidhur nga bllokimi i aplikacionit ose madje
ndarja e blloqeve të bazës së të dhënave Oracle. Është e drejtë—ka shpenzime të larta kur ndahen të dhënat
në blloqet e të dhënave! Por SLOB - në vendosjen e tij të paracaktuar - është imun ndaj një grindjeje të tillë.

Kjo deklaratë: korrespondon, është.
Është i përshtatshëm për të rregulluar shkallën e paralelizmit të seancave cl, ky është çelësi -t nisni programin runit.sh nga SLOB
Përqindja e komandave DML është e rregulluar, në numrin e mesazheve me tekst që dërgohen në subd, çdo sesion teksti, parametri UPDATE_PCT
Më vete dhe shumë të përshtatshme: SLOB vetë, para dhe pas seancës së ngarkimit - përgatit një statspack, ose awr-snapshots (ajo që është caktuar për t'u përgatitur).

Megjithatë, doli që SLOB nuk mbështet sesionet SQL me kohëzgjatje më të vogël se 30 sekonda.
Prandaj, së pari kodova versionin tim, punëtor-fshatar të ngarkuesit, dhe më pas ai mbeti në funksion.

Më lejoni të sqaroj se çfarë bën ngarkuesi dhe si e bën atë, për qartësi.
Në thelb ngarkuesi duket si ky:

Kodi i punëtorit

function dotx()
{
local v_period="$2"
[ -z "v_period" ] && v_period="0"
source "/home/oracle/testingredotracе/config.conf"

$ORACLE_HOME/bin/sqlplus -S system/${v_system_pwd} << __EOF__
whenever sqlerror exit failure
set verify off
set echo off
set feedback off

define wnum="$1"
define period="$v_period"
set appinfo worker_&&wnum

declare
 v_upto number;
 v_key  number;
 v_tots number;
 v_cts  number;
begin
 select max(col1) into v_upto from system.testtab_&&wnum;
 SELECT (( SYSDATE - DATE '1970-01-01' ) * 86400 ) into v_cts FROM DUAL;
 v_tots := &&period + v_cts;
 while v_cts <= v_tots
 loop
  v_key:=abs(mod(dbms_random.random,v_upto));
  if v_key=0 then
   v_key:=1;
  end if;
  update system.testtab_&&wnum t
  set t.object_name=translate(dbms_random.string('a', 120), 'abcXYZ', '158249')
  where t.col1=v_key
  ;
  commit;
  SELECT (( SYSDATE - DATE '1970-01-01' ) * 86400 ) into v_cts FROM DUAL;
 end loop;
end;
/

exit
__EOF__
}
export -f dotx

Punëtorët nisen në këtë mënyrë:

Punëtorët që vrapojnë

echo "starting test, duration: ${TEST_DURATION}" >> "$v_logfile"
for((i=1;i<="$SQLSESS_COUNT";i++))
do
 echo "sql-session: ${i}" >> "$v_logfile"
 dotx "$i" "${TEST_DURATION}" &
done
echo "waiting..." >> "$v_logfile"
wait

Dhe tabelat për punëtorët përgatiten si kjo:

Krijimi i tabelave

function createtable() {
source "/home/oracle/testingredotracе/config.conf"
$ORACLE_HOME/bin/sqlplus -S system/${v_system_pwd} << __EOF__
whenever sqlerror continue
set verify off
set echo off
set feedback off

define wnum="$1"
define ts_name="slob"

begin
 execute immediate 'drop table system.testtab_&&wnum';
exception when others then null;
end;
/

create table system.testtab_&&wnum tablespace &&ts_name as
select rownum as col1, t.*
from sys.dba_objects t
where rownum<1000
;
create index testtab_&&wnum._idx on system.testtab_&&wnum (col1);
--alter table system.testtab_&&wnum nologging;
--alter index system.testtab_&&wnum._idx nologging;
exit
__EOF__
}
export -f createtable

seq 1 1 "$SQLSESS_COUNT" | xargs -n 1 -P 4 -I {} -t bash -c "createtable "{}"" | tee -a "$v_logfile"
echo "createtable done" >> "$v_logfile"

Ato. Për çdo punëtor (praktikisht: një seancë e veçantë SQL në DB) krijohet një tabelë e veçantë, me të cilën punon punëtori.

Kjo siguron mungesën e bllokimeve të transaksioneve ndërmjet seancave të punëtorëve.
Secili punëtor: bën të njëjtën gjë, me tavolinën e tij, tavolinat janë të gjitha njësoj.
Të gjithë punëtorët kryejnë punë për të njëjtën kohë.
Për më tepër, për një kohë mjaft të gjatë në mënyrë që, për shembull, të ndodhte patjetër një ndërprerës i regjistrit, dhe më shumë se një herë.
Epo, në përputhje me rrethanat, u ngritën kostot dhe efektet e lidhura.
Në rastin tim, unë konfigurova kohëzgjatjen e punës së punëtorëve në 8 minuta.

Një pjesë e një raporti statspack që përshkruan funksionimin e subd nën ngarkesë

Database    DB Id    Instance     Inst Num  Startup Time   Release     RAC
~~~~~~~~ ----------- ------------ -------- --------------- ----------- ---
          2929910313 XE                  1 07-Sep-20 23:12 18.0.0.0.0  NO

Host Name             Platform                CPUs Cores Sockets   Memory (G)
~~~~ ---------------- ---------------------- ----- ----- ------- ------------
     billing.izhevsk1 Linux x86 64-bit           2     2       1         15.6

Snapshot       Snap Id     Snap Time      Sessions Curs/Sess Comment
~~~~~~~~    ---------- ------------------ -------- --------- ------------------
Begin Snap:       1630 07-Sep-20 23:12:27       55        .7
  End Snap:       1631 07-Sep-20 23:20:29       62        .6
   Elapsed:       8.03 (mins) Av Act Sess:       8.4
   DB time:      67.31 (mins)      DB CPU:      15.01 (mins)

Cache Sizes            Begin        End
~~~~~~~~~~~       ---------- ----------
    Buffer Cache:     1,392M              Std Block Size:         8K
     Shared Pool:       288M                  Log Buffer:   103,424K

Load Profile              Per Second    Per Transaction    Per Exec    Per Call
~~~~~~~~~~~~      ------------------  ----------------- ----------- -----------
      DB time(s):                8.4                0.0        0.00        0.20
       DB CPU(s):                1.9                0.0        0.00        0.04
       Redo size:        7,685,765.6              978.4
   Logical reads:           60,447.0                7.7
   Block changes:           47,167.3                6.0
  Physical reads:                8.3                0.0
 Physical writes:              253.4                0.0
      User calls:               42.6                0.0
          Parses:               23.2                0.0
     Hard parses:                1.2                0.0
W/A MB processed:                1.0                0.0
          Logons:                0.5                0.0
        Executes:           15,756.5                2.0
       Rollbacks:                0.0                0.0
    Transactions:            7,855.1

Kthimi në punën laboratorike.
Ne, duke qenë të barabarta, do të ndryshojmë vlerat e parametrave të mëposhtëm të nënbazës së të dhënave laboratorike:

  1. Madhësia e grupeve të regjistrave të bazës së të dhënave. diapazoni i vlerave: [32, 1024] MB;
  2. Numri i grupeve të ditarit në bazën e të dhënave. diapazoni i vlerave: [2,32];
  3. log_archive_max_processes diapazoni i vlerave: [1,8];
  4. commit_logging lejohen dy vlera: batch|immediate;
  5. commit_wait lejohen dy vlera: wait|nowait;
  6. log_buffer diapazoni i vlerës: [2,128] MB.
  7. log_checkpoint_timeout diapazoni i vlerave: [60,1200] sekonda
  8. db_writer_processes diapazoni i vlerave: [1,4]
  9. undo_retention diapazoni i vlerave: [30;300] sekonda
  10. transactions_per_rollback_segment diapazoni i vlerave: [1,8]
  11. disk_asynch_io lejohen dy vlera: true|false;
  12. filesystemio_options lejohen vlerat e mëposhtme: none|setall|directIO|asynch;
  13. db_block_checking lejohen vlerat e mëposhtme: OFF|LOW|MEDIUM|FULL;
  14. db_block_checksum lejohen vlerat e mëposhtme: OFF|TYPICAL|FULL;

Një person me përvojë në mirëmbajtjen e bazave të të dhënave Oracle me siguri tashmë mund të thotë se çfarë dhe në çfarë vlerash duhet të vendosen, nga parametrat e specifikuar dhe vlerat e tyre të pranueshme, në mënyrë që të marrë një produktivitet më të madh të bazës së të dhënave për punën me të dhënat që tregohen nga kodin e aplikimit, këtu më lart.

Por.

Qëllimi i punës laboratorike është të tregojë se vetë algoritmi i optimizimit do ta sqarojë këtë për ne relativisht shpejt.

Për ne, gjithçka që mbetet është të shikojmë dokumentin, përmes sistemit të personalizueshëm, mjafton të zbulojmë se cilat parametra duhet të ndryshohen dhe në çfarë diapazoni.
Dhe gjithashtu: kodoni kodin që do të përdoret për të punuar me sistemin personal të algoritmit të zgjedhur të optimizimit.

Pra, tani në lidhje me kodin.
Unë fola më lart për cran-r, d.m.th.: të gjitha manipulimet me sistemin e personalizuar janë të orkestruara në formën e një skripti R.

Detyra aktuale, analiza, përzgjedhja sipas vlerës metrike, vektorët e gjendjes së sistemit: kjo është një paketë GA (dokumentacionin)
Paketa, në këtë rast, nuk është shumë e përshtatshme, në kuptimin që pret që vektorët (kromozomet, nëse për sa i përket paketës) të specifikohen në formën e vargjeve të numrave me një pjesë thyesore.

Dhe vektori im, nga vlerat e parametrave të vendosjes: këto janë 14 sasi - numra të plotë dhe vlera të vargut.

Problemi, natyrisht, shmanget lehtësisht duke caktuar disa numra specifikë për vlerat e vargut.

Kështu, në fund, pjesa kryesore e skenarit R duket kështu:

Telefononi GA::ga

cat( "", file=v_logfile, sep="n", append=F)

pSize = 10
elitism_value=1
pmutation_coef=0.8
pcrossover_coef=0.1
iterations=50

gam=GA::ga(type="real-valued", fitness=evaluate,
lower=c(32,2, 1,1,1,2,60,1,30,1,0,0, 0,0), upper=c(1024,32, 8,10,10,128,800,4,300,8,10,40, 40,30),
popSize=pSize,
pcrossover = pcrossover_coef,
pmutation = pmutation_coef,
maxiter=iterations,
run=4,
keepBest=T)
cat( "GA-session is done" , file=v_logfile, sep="n", append=T)
gam@solution

Këtu, me ndihmën lower и upper atributet e nënrutinës ga në thelb, specifikohet një zonë e hapësirës së kërkimit, brenda së cilës do të kryhet një kërkim për një vektor (ose vektorë) të tillë për të cilin do të merret vlera maksimale e funksionit të fitnesit.

Nënprogrami ga kryen një kërkim duke maksimizuar funksionin e fitnesit.

Epo, atëherë, rezulton se, në këtë rast, është e nevojshme që funksioni i përshtatshmërisë, duke kuptuar vektorin si një grup vlerash për parametra të caktuar të subd, të marrë një metrikë nga subd.

Kjo është: sa, me një konfigurim të caktuar subd dhe një ngarkesë të caktuar në subd: subd përpunon transaksione për sekondë.

Kjo do të thotë, kur shpaloset, duhet të kryhet shumë-hapi i mëposhtëm brenda funksionit të fitnesit:

  1. Përpunimi i vektorit të hyrjes së numrave - shndërrimi i tij në vlera për parametrat e nëntë dhënave.
  2. Një përpjekje për të krijuar një numër të caktuar grupesh të ribërjes së një madhësie të caktuar. Për më tepër, përpjekja mund të jetë e pasuksesshme.
    Grupet e revistave që ekzistonin tashmë në nënd, në një sasi dhe në njëfarë madhësie, për pastërtinë e eksperimentit - d.b. fshihet.
  3. Nëse pika e mëparshme është e suksesshme: specifikimi i vlerave të parametrave të konfigurimit në bazën e të dhënave (përsëri: mund të ketë një dështim)
  4. Nëse hapi i mëparshëm është i suksesshëm: ndalimi i subd, fillimi i subd në mënyrë që vlerat e parametrave të specifikuara rishtas të hyjnë në fuqi. (përsëri: mund të ketë një defekt)
  5. Nëse hapi i mëparshëm është i suksesshëm: kryeni një test ngarkese. merrni metrikë nga subd.
  6. Kthejeni subd-në në gjendjen e tij origjinale, d.m.th. fshini grupet shtesë të regjistrave, ktheni në punë konfigurimin origjinal të bazës së të dhënave.

Kodi i funksionit të fitnesit

evaluate=function(p_par) {
v_module="evaluate"
v_metric=0
opn=NULL
opn$rg_size=round(p_par[1],digit=0)
opn$rg_count=round(p_par[2],digit=0)
opn$log_archive_max_processes=round(p_par[3],digit=0)
opn$commit_logging="BATCH"
if ( round(p_par[4],digit=0) > 5 ) {
 opn$commit_logging="IMMEDIATE"
}
opn$commit_logging=paste("'", opn$commit_logging, "'",sep="")

opn$commit_wait="WAIT"
if ( round(p_par[5],digit=0) > 5 ) {
 opn$commit_wait="NOWAIT"
}
opn$commit_wait=paste("'", opn$commit_wait, "'",sep="")

opn$log_buffer=paste(round(p_par[6],digit=0),"m",sep="")
opn$log_checkpoint_timeout=round(p_par[7],digit=0)
opn$db_writer_processes=round(p_par[8],digit=0)
opn$undo_retention=round(p_par[9],digit=0)
opn$transactions_per_rollback_segment=round(p_par[10],digit=0)
opn$disk_asynch_io="true"
if ( round(p_par[11],digit=0) > 5 ) {
 opn$disk_asynch_io="false"
} 

opn$filesystemio_options="none"
if ( round(p_par[12],digit=0) > 10 && round(p_par[12],digit=0) <= 20 ) {
 opn$filesystemio_options="setall"
}
if ( round(p_par[12],digit=0) > 20 && round(p_par[12],digit=0) <= 30 ) {
 opn$filesystemio_options="directIO"
}
if ( round(p_par[12],digit=0) > 30 ) {
 opn$filesystemio_options="asynch"
}

opn$db_block_checking="OFF"
if ( round(p_par[13],digit=0) > 10 && round(p_par[13],digit=0) <= 20 ) {
 opn$db_block_checking="LOW"
}
if ( round(p_par[13],digit=0) > 20 && round(p_par[13],digit=0) <= 30 ) {
 opn$db_block_checking="MEDIUM"
}
if ( round(p_par[13],digit=0) > 30 ) {
 opn$db_block_checking="FULL"
}

opn$db_block_checksum="OFF"
if ( round(p_par[14],digit=0) > 10 && round(p_par[14],digit=0) <= 20 ) {
 opn$db_block_checksum="TYPICAL"
}
if ( round(p_par[14],digit=0) > 20 ) {
 opn$db_block_checksum="FULL"
}

v_vector=paste(round(p_par[1],digit=0),round(p_par[2],digit=0),round(p_par[3],digit=0),round(p_par[4],digit=0),round(p_par[5],digit=0),round(p_par[6],digit=0),round(p_par[7],digit=0),round(p_par[8],digit=0),round(p_par[9],digit=0),round(p_par[10],digit=0),round(p_par[11],digit=0),round(p_par[12],digit=0),round(p_par[13],digit=0),round(p_par[14],digit=0),sep=";")
cat( paste(v_module," try to evaluate vector: ", v_vector,sep="") , file=v_logfile, sep="n", append=T)

rc=make_additional_rgroups(opn)
if ( rc!=0 ) {
 cat( paste(v_module,"make_additional_rgroups failed",sep="") , file=v_logfile, sep="n", append=T)
 return (0)
}

v_rc=0
rc=set_db_parameter("log_archive_max_processes", opn$log_archive_max_processes)
if ( rc != 0 ) {  v_rc=1 }
rc=set_db_parameter("commit_logging", opn$commit_logging )
if ( rc != 0 ) {  v_rc=1 }
rc=set_db_parameter("commit_wait", opn$commit_wait )
if ( rc != 0 ) {  v_rc=1 }
rc=set_db_parameter("log_buffer", opn$log_buffer )
if ( rc != 0 ) {  v_rc=1 }
rc=set_db_parameter("log_checkpoint_timeout", opn$log_checkpoint_timeout )
if ( rc != 0 ) {  v_rc=1 }
rc=set_db_parameter("db_writer_processes", opn$db_writer_processes )
if ( rc != 0 ) {  v_rc=1 }
rc=set_db_parameter("undo_retention", opn$undo_retention )
if ( rc != 0 ) {  v_rc=1 }
rc=set_db_parameter("transactions_per_rollback_segment", opn$transactions_per_rollback_segment )
if ( rc != 0 ) {  v_rc=1 }
rc=set_db_parameter("disk_asynch_io", opn$disk_asynch_io )
if ( rc != 0 ) {  v_rc=1 }
rc=set_db_parameter("filesystemio_options", opn$filesystemio_options )
if ( rc != 0 ) {  v_rc=1 }
rc=set_db_parameter("db_block_checking", opn$db_block_checking )
if ( rc != 0 ) {  v_rc=1 }
rc=set_db_parameter("db_block_checksum", opn$db_block_checksum )
if ( rc != 0 ) {  v_rc=1 }

if ( rc!=0 ) {
 cat( paste(v_module," can not startup db with that vector of settings",sep="") , file=v_logfile, sep="n", append=T)
 rc=stop_db("immediate")
 rc=create_spfile()
 rc=start_db("")
 rc=remove_additional_rgroups(opn)
 return (0)
}

rc=stop_db("immediate")
rc=start_db("")
if ( rc!=0 ) {
 cat( paste(v_module," can not startup db with that vector of settings",sep="") , file=v_logfile, sep="n", append=T)
 rc=stop_db("abort")
 rc=create_spfile()
 rc=start_db("")
 rc=remove_additional_rgroups(opn)
 return (0)
}

rc=run_test()
v_metric=getmetric()

rc=stop_db("immediate")
rc=create_spfile()
rc=start_db("")
rc=remove_additional_rgroups(opn)

cat( paste("result: ",v_metric," ",v_vector,sep="") , file=v_logfile, sep="n", append=T)
return (v_metric)
}

Se. e gjithë puna: kryhet në funksionin e fitnesit.

Nënrutina ga përpunon vektorët, ose, më saktë, kromozomet.
Në të cilën, ajo që është më e rëndësishme për ne është përzgjedhja e kromozomeve me gjene për të cilat funksioni i fitnesit prodhon vlera të mëdha.

Ky, në thelb, është procesi i kërkimit të grupit optimal të kromozomeve duke përdorur një vektor në një hapësirë ​​kërkimi N-dimensionale.

Shumë e qartë, e detajuar shpjegim, me shembuj të kodit R, puna e një algoritmi gjenetik.

Unë do të doja të shënoja veçmas dy pika teknike.

Thirrjet ndihmëse nga funksioni evaluate, për shembull, stop-start, vendosja e vlerës së parametrit subd, kryhen bazuar në cran-r funksione system2

Me ndihmën e së cilës: thirret ndonjë skrip ose komandë bash.

Për shembull:

vendos_db_parametri

set_db_parameter=function(p1, p2) {
v_module="set_db_parameter"
v_cmd="/home/oracle/testingredotracе/set_db_parameter.sh"
v_args=paste(p1," ",p2,sep="")

x=system2(v_cmd, args=v_args, stdout=T, stderr=T, wait=T)
if ( length(attributes(x)) > 0 ) {
 cat(paste(v_module," failed with: ",attributes(x)$status," ",v_cmd," ",v_args,sep=""), file=v_logfile, sep="n", append=T)
 return (attributes(x)$status)
}
else {
 cat(paste(v_module," ok: ",v_cmd," ",v_args,sep=""), file=v_logfile, sep="n", append=T)
 return (0)
}
}

Pika e dytë është vija, evaluate funksionet, me ruajtjen e një vlere specifike metrike dhe vektorin e saj akordues përkatës në një skedar log:

cat( paste("result: ",v_metric," ",v_vector,sep="") , file=v_logfile, sep="n", append=T)

Kjo është e rëndësishme, sepse nga ky grup i të dhënave, do të jetë e mundur të merret informacion shtesë se cili nga komponentët e vektorit akordues ka një efekt më të madh ose më të vogël në vlerën metrike.

Kjo do të thotë: do të jetë e mundur të kryhet analiza atribut-importamce.

Pra, çfarë mund të ndodhë?

Në formën e grafikut, nëse i renditni testet në rend metrikë në rritje, fotografia është si më poshtë:

Metoda e poke shkencore, ose si të zgjidhni një konfigurim të bazës së të dhënave duke përdorur standarde dhe një algoritëm optimizimi

Disa të dhëna që korrespondojnë me vlerat ekstreme të metrikës:
Metoda e poke shkencore, ose si të zgjidhni një konfigurim të bazës së të dhënave duke përdorur standarde dhe një algoritëm optimizimi
Këtu, në pamjen e ekranit me rezultatet, do të sqaroj: vlerat e vektorit të akordimit janë dhënë për sa i përket kodit të funksionit të përshtatshmërisë, jo për sa i përket listës së numrave të parametrave / diapazoneve të vlerave të parametrave, e cila është formuluar. sipër në tekst.

Epo. A është shumë apo pak, ~8 mijë tps: një pyetje më vete.
Në kuadër të punës laboratorike kjo shifër nuk është e rëndësishme, e rëndësishme është dinamika, si ndryshon kjo vlerë.

Dinamika këtu është e mirë.
Është e qartë se të paktën një faktor ndikon ndjeshëm në vlerën e metrikës, ga-algoritmi, renditja përmes vektorëve të kromozomeve: mbuluar.
Duke gjykuar nga dinamika mjaft e fuqishme e vlerave të kurbës, ka të paktën një faktor më shumë që, megjithëse dukshëm më i vogël, ka një ndikim.

Kjo është ajo ku ju duhet attribute-importance analiza për të kuptuar se cilat atribute (mirë, në këtë rast, përbërës të vektorit akordues) dhe sa ndikojnë ato në vlerën metrike.
Dhe nga ky informacion: kuptoni se cilët faktorë u ndikuan nga ndryshimet në atributet e rëndësishme.

Ekzekutuar attribute-importance të mundshme në mënyra të ndryshme.

Për këto qëllime, më pëlqen algoritmi randomForest Paketa R me të njëjtin emër (dokumentacionin)
randomForest, siç e kuptoj punën e tij në përgjithësi dhe qasjen e tij për vlerësimin e rëndësisë së atributeve në veçanti, ndërton një model të caktuar të varësisë së variablit të përgjigjes nga atributet.

Në rastin tonë, ndryshorja e përgjigjes është një metrikë e marrë nga baza e të dhënave në testet e ngarkesës: tps;
Dhe atributet janë përbërës të vektorit akordues.

kështu që këtu randomForest vlerëson rëndësinë e secilit atribut model me dy numra: %IncMSE — si e ndryshon prania/mungesa e këtij atributi në një model cilësinë e MSE të këtij modeli (Gabimi mesatar në katror);

Dhe IncNodePurity është një numër që pasqyron se sa mirë, bazuar në vlerat e këtij atributi, mund të ndahet një grup të dhënash me vëzhgime, në mënyrë që në një pjesë të ketë të dhëna me një vlerë të metrikës që shpjegohet, dhe në tjetrën me një vlerë tjetër e metrikës.
Epo, kjo është: deri në çfarë mase është ky një atribut klasifikues (pashë shpjegimin më të qartë, në gjuhën ruse në RandomForest këtu).

Kodi R punëtor-fshatar për përpunimin e një grupi të dhënash me rezultatet e testeve të ngarkesës:

x=NULL
v_data_file=paste('/tmp/data1.dat',sep="")
x=read.table(v_data_file, header = TRUE, sep = ";", dec=",", quote = ""'", stringsAsFactors=FALSE)
colnames(x)=c('metric','rgsize','rgcount','lamp','cmtl','cmtw','lgbffr','lct','dbwrp','undo_retention','tprs','disk_async_io','filesystemio_options','db_block_checking','db_block_checksum')

idxTrain=sample(nrow(x),as.integer(nrow(x)*0.7))
idxNotTrain=which(! 1:nrow(x) %in% idxTrain )
TrainDS=x[idxTrain,]
ValidateDS=x[idxNotTrain,]

library(randomForest)
#mtry=as.integer( sqrt(dim(x)[2]-1) )
rf=randomForest(metric ~ ., data=TrainDS, ntree=40, mtry=3, replace=T, nodesize=2, importance=T, do.trace=10, localImp=F)
ValidateDS$predicted=predict(rf, newdata=ValidateDS[,colnames(ValidateDS)!="metric"], type="response")
sum((ValidateDS$metric-ValidateDS$predicted)^2)
rf$importance

Ju mund të zgjidhni direkt hiperparametrat e algoritmit me duart tuaja dhe, duke u fokusuar në cilësinë e modelit, zgjidhni një model që përmbush më saktë parashikimet në grupin e të dhënave të vlefshmërisë.
Ju mund të shkruani një lloj funksioni për këtë punë (nga rruga, përsëri, duke përdorur një lloj algoritmi optimizimi).

Ju mund të përdorni paketën R caret, nuk është pika e rëndësishme.

Si rezultat, në këtë rast, rezultati i mëposhtëm merret për të vlerësuar shkallën e rëndësisë së atributeve:

Metoda e poke shkencore, ose si të zgjidhni një konfigurim të bazës së të dhënave duke përdorur standarde dhe një algoritëm optimizimi

Epo. Kështu, ne mund të fillojmë reflektimin global:

  1. Rezulton se më i rëndësishmi, në këto kushte testimi, ishte parametri commit_wait
    Teknikisht, ai specifikon mënyrën e ekzekutimit të operacionit io të shkrimit të të dhënave të ribërjes nga buferi i regjistrit të subdb në grupin aktual të regjistrave: sinkron ose asinkron.
    Vlerë nowait që rezulton në një rritje pothuajse vertikale, të shumëfishtë në vlerën e metrikës tps: ky është përfshirja e modalitetit io asinkron në grupet e ribërjes.
    Një pyetje më vete është nëse duhet ta bëni këtë në një bazë të dhënash ushqimore. Këtu kufizohem vetëm në deklarimin: ky është një faktor domethënës.
  2. Është logjike që madhësia e tamponit log të subd: rezulton të jetë një faktor i rëndësishëm.
    Sa më e vogël të jetë madhësia e buferit log, aq më pak kapaciteti i tij buferik, aq më shpesh ai tejmbush dhe/ose pamundësia për të ndarë një zonë të lirë në të për një pjesë të të dhënave të reja redoks.
    Kjo do të thotë: vonesa të lidhura me ndarjen e hapësirës në buferin e regjistrit dhe/ose hedhjen e të dhënave të ribërjes prej tij në grupe të ribërjes.
    Këto vonesa, natyrisht, duhet dhe ndikojnë në qarkullimin e bazës së të dhënave për transaksionet.
  3. Parametër db_block_checksum: mirë, gjithashtu, në përgjithësi është e qartë - përpunimi i transaksioneve çon në formimin e blloqeve darty në cache-in e tamponit të nënbazës së të dhënave.
    Të cilat, kur aktivizohet kontrollimi i shumave të kontrollit të blloqeve të të dhënave, baza e të dhënave duhet t'i përpunojë - llogaritë këto kontrolle nga trupi i bllokut të të dhënave, kontrolloni ato me atë që është shkruar në kokën e bllokut të të dhënave: përputhet/nuk përputhet.
    Një punë e tillë, përsëri, nuk mund të mos vonojë përpunimin e të dhënave, dhe në përputhje me rrethanat, parametri dhe mekanizmi që vendos këtë parametër rezultojnë të jenë domethënës.
    Kjo është arsyeja pse shitësi ofron, në dokumentacionin për këtë parametër, vlera të ndryshme për të (parametrin) dhe vëren se po, do të ketë një ndikim, por, mirë, mund të zgjidhni vlera të ndryshme, deri në "off" dhe ndikime të ndryshme.

Epo, një përfundim global.

Qasja, në përgjithësi, rezulton të jetë mjaft funksionale.

Ai e lejon mjaft veten, në fazat e hershme të testimit të ngarkesës të një sistemi të caktuar shërbimi, në mënyrë që të zgjedhë konfigurimin e tij (sistemi) optimal për ngarkesën, të mos thellohet shumë në specifikat e konfigurimit të sistemit për ngarkesën.

Por nuk e përjashton plotësisht - të paktën në nivelin e të kuptuarit: sistemi duhet të njihet për "pullat e rregullimit" dhe diapazonin e lejueshëm të rrotullimit të këtyre pullave.

Qasja më pas mund të gjejë relativisht shpejt konfigurimin optimal të sistemit.
Dhe bazuar në rezultatet e testimit, është e mundur të merret informacion në lidhje me natyrën e marrëdhënies midis matjeve të performancës së sistemit dhe vlerave të parametrave të cilësimeve të sistemit.

E cila, natyrisht, duhet të kontribuojë në shfaqjen e këtij kuptimi shumë të thellë të sistemit, funksionimin e tij, të paktën nën një ngarkesë të caktuar.

Në praktikë, ky është një shkëmbim i kostove të të kuptuarit të sistemit të personalizuar për kostot e përgatitjes së një testimi të tillë të sistemit.

Do të doja të shënoja veçmas: në këtë qasje, shkalla e përshtatshmërisë së testimit të sistemit me kushtet e funksionimit që do të ketë në funksionimin komercial është jashtëzakonisht e rëndësishme.

Faleminderit për vëmendjen dhe kohën tuaj.

Burimi: www.habr.com

Shto një koment