El mètode científic de poke, o com seleccionar una configuració de base de dades mitjançant benchmarks i un algorisme d'optimització

Hola

Vaig decidir compartir la meva troballa, fruit del pensament, l'assaig i l'error.
En general: això no és una troballa, per descomptat; tot això hauria d'haver estat conegut des de fa molt de temps per a aquells que estan implicats en el processament de dades estadístiques aplicades i l'optimització de qualsevol sistema, no necessàriament específicament el SGBD.
I: sí, ho saben, escriuen articles interessants sobre la seva recerca, exemple (UPD.: en els comentaris van assenyalar un projecte molt interessant: llúdriga )
D'altra banda: no veig cap menció o difusió generalitzada d'aquest enfocament a Internet entre els informàtics, DBA.

Per tant, fins al punt.

Suposem que tenim una tasca: configurar un determinat sistema de servei per donar servei a algun tipus de treball.

Se sap d'aquesta obra: què és, com es mesura la qualitat d'aquesta obra i quin és el criteri per mesurar aquesta qualitat.

Suposem també que és més o menys conegut i s'entén: exactament com es treballa en (o amb) aquest sistema de serveis.

"Més o menys": això vol dir que és possible preparar (o obtenir-lo des d'algun lloc) una determinada eina, utilitat, servei que es pot sintetitzar i aplicar al sistema amb una càrrega de prova suficientment adequada al que estarà en producció, en condicions prou adequades per treballar en la producció.

Bé, suposem que es coneix un conjunt de paràmetres d'ajust d'aquest sistema de servei, que es poden utilitzar per configurar aquest sistema pel que fa a la productivitat del seu treball.

I quin és el problema: no hi ha una comprensió prou completa d'aquest sistema de servei, que us permeti configurar de manera experta la configuració d'aquest sistema per a la càrrega futura en una plataforma determinada i obtenir la productivitat necessària del sistema.

Bé. Aquest és gairebé sempre el cas.

Què pots fer aquí?

Bé, el primer que em ve al cap és mirar la documentació d'aquest sistema. Comprendre quins són els intervals acceptables per als valors dels paràmetres d'ajust. I, per exemple, utilitzant el mètode de descens de coordenades, seleccioneu valors per als paràmetres del sistema a les proves.

Aquells. donar al sistema algun tipus de configuració, en forma d'un conjunt específic de valors per als seus paràmetres de configuració.

Apliqueu-hi una càrrega de prova, utilitzant aquesta eina-utilitat, generador de càrrega.
I mireu el valor: la resposta o una mètrica de la qualitat del sistema.

El segon pensament pot ser la conclusió que això és molt llarg.

Bé, és a dir: si hi ha molts paràmetres d'ajust, si els rangs dels seus valors coberts són grans, si cada prova de càrrega individual triga molt de temps a completar-se, aleshores: sí, tot això pot trigar una quantitat inacceptable de temps.

Bé, aquí teniu el que podeu entendre i recordar.

Podeu esbrinar que al conjunt de valors dels paràmetres de configuració del sistema de servei hi ha un vector, com una seqüència d'alguns valors.

Cada vector d'aquest tipus, en igualtat de coses (ja que no es veu afectat per aquest vector), correspon a un valor completament definit de la mètrica, un indicador de la qualitat del funcionament del sistema sota una càrrega de prova.

És a dir,

Denotem el vector de configuració del sistema com a El mètode científic de poke, o com seleccionar una configuració de base de dades mitjançant benchmarks i un algorisme d'optimitzacióOn El mètode científic de poke, o com seleccionar una configuració de base de dades mitjançant benchmarks i un algorisme d'optimització; On El mètode científic de poke, o com seleccionar una configuració de base de dades mitjançant benchmarks i un algorisme d'optimització — nombre de paràmetres de configuració del sistema, quants d'aquests paràmetres hi ha.

I el valor de la mètrica corresponent a aquesta El mètode científic de poke, o com seleccionar una configuració de base de dades mitjançant benchmarks i un algorisme d'optimització denotem-ho com
El mètode científic de poke, o com seleccionar una configuració de base de dades mitjançant benchmarks i un algorisme d'optimització, llavors obtenim una funció: El mètode científic de poke, o com seleccionar una configuració de base de dades mitjançant benchmarks i un algorisme d'optimització

Bé, doncs: tot es redueix immediatament a, en el meu cas: gairebé oblidat des dels meus temps d'estudiant, algorismes per buscar l'extrem d'una funció.

D'acord, però aquí sorgeix una pregunta organitzativa i aplicada: quin algorisme utilitzar.

  1. En el sentit, perquè pugueu codificar menys a mà.
  2. I perquè funcioni, és a dir. va trobar l'extrem (si n'hi ha), bé, almenys més ràpid que el descens de coordenades.

El primer punt indica que hem de mirar cap a alguns entorns en què aquests algorismes ja s'han implementat i, d'alguna manera, estan preparats per utilitzar-los en codi.
Bé, ho sé python и cran-r

El segon punt significa que cal llegir sobre els propis algorismes, què són, quins són els seus requisits, les característiques del seu treball.

I el que donen poden ser efectes secundaris útils: resultats o directament del propi algorisme.

O es poden obtenir a partir dels resultats de l'algorisme.

Molt depèn de les condicions d'entrada.

Per exemple, si, per alguna raó, necessiteu obtenir un resultat més ràpid, bé, heu de mirar cap als algorismes de descens de gradients i triar-ne un.

O, si el temps no és tan important, podeu, per exemple, utilitzar mètodes d'optimització estocàstica, com un algorisme genètic.

Proposo considerar el treball d'aquest enfocament, seleccionant la configuració del sistema, utilitzant un algorisme genètic, en el següent, per dir-ho així: treball de laboratori.

Original:

  1. Que hi hagi, com a sistema de serveis: oracle xe 18c
  2. Deixa que serveixi per a l'activitat transaccional i l'objectiu: obtenir el màxim rendiment possible de la subbase de dades, en transaccions/s.
  3. Les transaccions poden ser molt diferents en la naturalesa de treballar amb dades i en el context de treball.
    Estem d'acord que es tracta de transaccions que no processen una gran quantitat de dades tabulars.
    En el sentit que no generen més dades de desfer que de refer i no processen grans percentatges de files i taules grans.

Són transaccions que canvien una fila en una taula més o menys gran, amb un nombre reduït d'índexs en aquesta taula.

En aquesta situació: la productivitat de la subbase de dades per processar les transaccions estarà determinada, amb reserva, per la qualitat del processament de la base de dades redox.

Exempció de responsabilitat: si parlem específicament de la configuració de subdb.

Perquè, en el cas general, pot haver-hi, per exemple, bloquejos transaccionals entre sessions SQL, a causa del disseny del treball de l'usuari amb dades tabulars i/o el model tabular.

La qual cosa, per descomptat, tindrà un efecte depriment en la mètrica TPS i aquest serà un factor exògen, en relació a la subbase de dades: bé, així és com es va dissenyar el model tabular i el treball amb les dades que hi ha que es produeixen bloquejos.

Per tant, per a la puresa de l'experiment, exclourem aquest factor, i a continuació us explicaré exactament com.

  1. Suposem, per a la definició, que el 100% de les ordres SQL enviades a la base de dades són ordres DML.
    Deixeu que les característiques del treball de l'usuari amb la subbase de dades siguin les mateixes a les proves.
    És a dir: el nombre de sessions skl, dades tabulars, com funcionen les sessions skl amb elles.
  2. Subd funciona a FORCE LOGGING, ARCHIVELOG mods. El mode de base de dades Flashback està desactivat, al nivell subd.
  3. Redo logs: situats en un sistema de fitxers separat, en un "disc" separat;
    La resta del component físic de la base de dades: en un altre sistema de fitxers independent, en un "disc" separat:

Més detalls sobre el dispositiu físic. components de la base de dades del laboratori

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

Inicialment, en aquestes condicions de càrrega, volia utilitzar subd de transacció SLOB-utilitat
Té una característica tan meravellosa, citaré l'autor:

Al cor de SLOB hi ha el "mètode SLOB". El Mètode SLOB té com a objectiu provar plataformes
sense contenció d'aplicació. No es pot impulsar el màxim rendiment del maquinari
utilitzant codi d'aplicació que, per exemple, està lligat al bloqueig de l'aplicació o fins i tot
compartir blocs de base de dades Oracle. Així és: hi ha una sobrecàrrega quan es comparteixen dades
en blocs de dades! Però SLOB, en el seu desplegament predeterminat, és immune a aquesta contenció.

Aquesta declaració: correspon, és.
És convenient regular el grau de paral·lelisme de les sessions cl, aquesta és la clau -t llançar la utilitat runit.sh de SLOB
El percentatge d'ordres DML està regulat, en el nombre de missatges de text que s'envien al subd, cada sessió de text, paràmetre UPDATE_PCT
Per separat i molt còmode: SLOB ell mateix, abans i després de la sessió de càrrega: prepara un paquet d'estadístiques o instantànies awr (el que s'ha de preparar).

No obstant això, va resultar que SLOB no admet sessions SQL amb una durada inferior a 30 segons.
Per tant, primer vaig codificar la meva pròpia versió, obrer-camperola, del carregador i després va romandre en funcionament.

Permeteu-me aclarir sobre el carregador: què i com fa, per a més claredat.
Bàsicament, el carregador té aquest aspecte:

Codi de treballador

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

Els treballadors es posen en marxa d'aquesta manera:

Treballadors corrents

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

I les taules per als treballadors es preparen així:

Creació de taules

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"

Aquells. Per a cada treballador (pràcticament: una sessió SQL separada a la base de dades) es crea una taula separada, amb la qual treballa el treballador.

Això garanteix l'absència de bloquejos transaccionals entre sessions de treballador.
Cada treballador: fa el mateix, amb la seva pròpia taula, les taules són totes iguals.
Tots els treballadors realitzen treballs durant el mateix temps.
A més, durant un temps prou llarg perquè, per exemple, es produeixi definitivament un canvi de registre, i més d'una vegada.
Bé, en conseqüència, van sorgir costos i efectes associats.
En el meu cas, he configurat la durada del treball dels treballadors en 8 minuts.

Una peça d'un informe d'estadístiques que descriu el funcionament de la substància sota càrrega

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

Retorn al treball de laboratori.
En igualtat de coses, variarem els valors dels següents paràmetres de la subbase de dades de laboratori:

  1. Mida dels grups de registre de la base de dades. rang de valors: [32, 1024] MB;
  2. Nombre de grups de revistes a la base de dades. rang de valors: [2,32];
  3. log_archive_max_processes rang de valors: [1,8];
  4. commit_logging es permeten dos valors: batch|immediate;
  5. commit_wait es permeten dos valors: wait|nowait;
  6. log_buffer rang de valors: [2,128] MB.
  7. log_checkpoint_timeout rang de valors: [60,1200] segons
  8. db_writer_processes rang de valors: [1,4]
  9. undo_retention rang de valors: [30;300] segons
  10. transactions_per_rollback_segment rang de valors: [1,8]
  11. disk_asynch_io es permeten dos valors: true|false;
  12. filesystemio_options es permeten els valors següents: none|setall|directIO|asynch;
  13. db_block_checking es permeten els valors següents: OFF|LOW|MEDIUM|FULL;
  14. db_block_checksum es permeten els valors següents: OFF|TYPICAL|FULL;

Una persona amb experiència en el manteniment de bases de dades Oracle segurament ja pot dir quins i a quins valors s'han de fixar, a partir dels paràmetres especificats i els seus valors acceptables, per tal d'obtenir una major productivitat de la base de dades per al treball amb les dades que s'indica per el codi de l'aplicació, aquí a dalt.

Però.

L'objectiu del treball de laboratori és demostrar que el propi algorisme d'optimització ens ho aclarirà amb relativa rapidesa.

A nosaltres només ens queda mirar el document, a través del sistema personalitzable, prou per saber quins paràmetres canviar i en quins rangs.
I també: codificar el codi que s'utilitzarà per treballar amb el sistema personalitzat de l'algorisme d'optimització seleccionat.

Per tant, ara sobre el codi.
He parlat més amunt cran-r, és a dir: totes les manipulacions amb el sistema personalitzat s'orquestren en forma d'un script R.

La tasca real, anàlisi, selecció per valor mètric, vectors d'estat del sistema: això és un paquet GA (documentació)
El paquet, en aquest cas, no és molt adequat, en el sentit que s'espera que els vectors (cromosomes, si es tracta del paquet) s'especifiquen en forma de cadenes de nombres amb una part fraccionada.

I el meu vector, a partir dels valors dels paràmetres de configuració: aquestes són 14 quantitats: nombres enters i valors de cadena.

El problema, per descomptat, s'evita fàcilment assignant alguns números específics a valors de cadena.

Així, al final, la peça principal de l'script R té aquest aspecte:

Truqueu a 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

Aquí, amb l'ajuda lower и upper atributs de subrutina ga essencialment, s'especifica una àrea de l'espai de cerca, dins de la qual es realitzarà una cerca d'aquest vector (o vectors) per als quals s'obtindrà el valor màxim de la funció de fitness.

La subrutina ga realitza una cerca maximitzant la funció de fitness.

Bé, doncs, resulta que, en aquest cas, és necessari que la funció de fitness, entenent el vector com un conjunt de valors per a determinats paràmetres del subd, rebi una mètrica del subd.

És a dir: quants, amb una configuració determinada de subd i una càrrega determinada sobre el subd: el subd processa transaccions per segon.

És a dir, quan es desplega, s'han de realitzar els següents passos múltiples dins de la funció de fitness:

  1. Processament del vector d'entrada de nombres: convertint-lo en valors per als paràmetres de subdades.
  2. Un intent de crear un nombre determinat de grups de refer d'una mida determinada. A més, l'intent pot ser infructuós.
    Grups de revistes que ja existien al subd, en certa quantitat i d'alguna mida, per la puresa de l'experiment - d.b. esborrat.
  3. Si el punt anterior té èxit: especificant els valors dels paràmetres de configuració a la base de dades (de nou: pot haver-hi un error)
  4. Si el pas anterior té èxit: aturar el subd, iniciar el subd perquè els valors dels paràmetres recentment especificats tinguin efecte. (de nou: pot haver-hi un error)
  5. Si el pas anterior té èxit: feu una prova de càrrega. obtenir mètriques de subd.
  6. Retorna el subs al seu estat original, és a dir. suprimiu grups de registre addicionals, torneu a funcionar la configuració original de la subbase de dades.

Codi de funció de fitness

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

Això. tot el treball: realitzat en la funció de fitness.

La subrutina ga processa vectors o, més correctament, cromosomes.
En el qual, el més important per a nosaltres és la selecció de cromosomes amb gens per als quals la funció de fitness produeix grans valors.

Aquest, en essència, és el procés de cerca del conjunt òptim de cromosomes mitjançant un vector en un espai de cerca N-dimensional.

Molt clar, detallat explicació, amb exemples de codi R, el treball d'un algorisme genètic.

M'agradaria destacar per separat dos aspectes tècnics.

Trucades auxiliars de la funció evaluate, per exemple, stop-start, establint el valor del paràmetre subd, es realitzen en funció de cran-r funcions system2

Amb l'ajuda del qual: es crida algun script o ordre bash.

Per exemple:

set_db_parameter

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

El segon punt és la línia, evaluate funcions, amb desar un valor mètric específic i el seu vector de sintonització corresponent en un fitxer de registre:

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

Això és important, perquè a partir d'aquesta matriu de dades, serà possible obtenir informació addicional sobre quins dels components del vector d'afinació té un efecte més o menys important en el valor mètric.

És a dir: es podrà realitzar una anàlisi d'atribut-importància.

Aleshores, què pot passar?

En forma de gràfic, si ordeneu les proves en ordre mètric ascendent, la imatge és la següent:

El mètode científic de poke, o com seleccionar una configuració de base de dades mitjançant benchmarks i un algorisme d'optimització

Algunes dades corresponents als valors extrems de la mètrica:
El mètode científic de poke, o com seleccionar una configuració de base de dades mitjançant benchmarks i un algorisme d'optimització
Aquí, a la captura de pantalla amb els resultats, aclareixo: els valors del vector de sintonització es donen en termes del codi de la funció de fitness, no en termes de la llista numèrica de paràmetres/intervals de valors de paràmetres, que es va formular més amunt en el text.

Bé. És molt o poc, ~8 mil tps: una pregunta a part.
En el marc del treball de laboratori, aquesta xifra no és important, l'important és la dinàmica, com canvia aquest valor.

La dinàmica aquí és bona.
És obvi que almenys un factor influeix significativament en el valor de la mètrica, l'algoritme ga, ordenant els vectors cromosòmics: cobert.
A jutjar per la dinàmica força vigorosa dels valors de la corba, hi ha almenys un factor més que, encara que significativament menor, influeix.

Aquí és on ho necessites attribute-importance anàlisi per entendre quins atributs (bé, en aquest cas, components del vector d'afinació) i quant influeixen en el valor mètric.
I a partir d'aquesta informació: entendre quins factors es van veure afectats pels canvis en els atributs significatius.

Executar attribute-importance possible de diferents maneres.

Per a aquests propòsits, m'agrada l'algoritme randomForest paquet R del mateix nom (documentació)
randomForest, tal com entenc el seu treball en general i el seu enfocament per avaluar la importància dels atributs en particular, construeix un cert model de dependència de la variable resposta dels atributs.

En el nostre cas, la variable resposta és una mètrica obtinguda de la base de dades en proves de càrrega: tps;
I els atributs són components del vector d'afinació.

I així randomForest avalua la importància de cada atribut del model amb dos números: %IncMSE — com la presència/absència d'aquest atribut en un model canvia la qualitat MSE d'aquest model (Error quadrat mitjà);

I IncNodePurity és un número que reflecteix com de bé, a partir dels valors d'aquest atribut, es pot dividir un conjunt de dades amb observacions, de manera que en una part hi ha dades amb un valor de la mètrica que s'explica, i en l'altra amb un altre valor de la mètrica.
Bé, és a dir: fins a quin punt aquest és un atribut de classificació (he vist l'explicació més clara en rus a RandomForest? aquí).

Codi R obrer-camperol per processar un conjunt de dades amb els resultats de les proves de càrrega:

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

Podeu seleccionar directament els hiperparàmetres de l'algorisme amb les vostres mans i, centrant-vos en la qualitat del model, seleccionar un model que compleixi amb més precisió les prediccions del conjunt de dades de validació.
Podeu escriure algun tipus de funció per a aquest treball (per cert, de nou, utilitzant algun tipus d'algorisme d'optimització).

Podeu utilitzar el paquet R caret, el punt no és important.

Com a resultat, en aquest cas, s'obté el resultat següent per avaluar el grau d'importància dels atributs:

El mètode científic de poke, o com seleccionar una configuració de base de dades mitjançant benchmarks i un algorisme d'optimització

Bé. Així, podem començar una reflexió global:

  1. Resulta que el més significatiu, en aquestes condicions de prova, va ser el paràmetre commit_wait
    Tècnicament, especifica el mode d'execució de l'operació io d'escriure dades de refer des del buffer de registre subdb al grup de registre actual: síncron o asíncron.
    Valor nowait que es tradueix en un augment gairebé vertical i múltiple del valor de la mètrica tps: es tracta de la inclusió del mode io asíncron en els grups redo.
    Una pregunta a part és si hauríeu de fer-ho o no en una base de dades d'aliments. Aquí em limito a afirmar: aquest és un factor important.
  2. És lògic que la mida de la memòria intermèdia de registre del subd: resulti ser un factor important.
    Com més petita sigui la mida de la memòria intermèdia de registre, menor serà la seva capacitat de memòria intermèdia, més sovint es desbordarà i/o la incapacitat d'assignar-hi una àrea lliure per a una part de les dades redox noves.
    Això vol dir: retards associats amb l'assignació d'espai a la memòria intermèdia de registre i/o l'abocament de dades de refer a grups de refer.
    Aquests retards, per descomptat, haurien d'afectar i afecten el rendiment de la base de dades per a les transaccions.
  3. Paràmetre db_block_checksum: bé, també, en general està clar: el processament de transaccions condueix a la formació de blocs darty a la memòria cau de memòria intermèdia de la subbase de dades.
    La qual cosa, quan està habilitat la comprovació de les sumes de control dels blocs de dades, la base de dades ha de processar: calcular aquestes sumes de comprovació a partir del cos del bloc de dades, comprovar-les amb el que està escrit a la capçalera del bloc de dades: coincideix/no coincideix.
    Aquest treball, de nou, no pot deixar de retardar el processament de les dades i, en conseqüència, el paràmetre i el mecanisme que estableix aquest paràmetre resulten importants.
    És per això que el venedor ofereix, a la documentació d'aquest paràmetre, diferents valors per a aquest (el paràmetre) i assenyala que sí, hi haurà un impacte, però, bé, podeu triar diferents valors, fins a "off" i diferents impactes.

Bé, una conclusió global.

L'enfocament, en general, resulta bastant funcional.

Es permet bastant, en les primeres etapes de les proves de càrrega d'un determinat sistema de servei, per seleccionar la seva configuració òptima (del sistema) per a la càrrega, no aprofundir massa en els detalls de la configuració del sistema per a la càrrega.

Però no ho exclou completament, almenys a nivell de comprensió: el sistema s'ha de conèixer sobre els "botons d'ajust" i els intervals de rotació admissibles d'aquests pols.

Aleshores, l'enfocament pot trobar relativament ràpidament la configuració òptima del sistema.
I a partir dels resultats de les proves, és possible obtenir informació sobre la naturalesa de la relació entre les mètriques de rendiment del sistema i els valors dels paràmetres de configuració del sistema.

La qual cosa, per descomptat, hauria de contribuir a l'aparició d'aquesta comprensió tan profunda del sistema, del seu funcionament, almenys sota una càrrega determinada.

A la pràctica, es tracta d'un intercanvi dels costos d'entendre el sistema personalitzat pels costos de preparar aquestes proves del sistema.

M'agradaria assenyalar per separat: en aquest enfocament, el grau d'adequació de les proves del sistema a les condicions de funcionament que tindrà en l'operació comercial és de gran importància.

Gràcies per la vostra atenció i temps.

Font: www.habr.com

Afegeix comentari