Olá
Decidi compartilhar minha descoberta - fruto de reflexão, tentativa e erro.
Em geral: isso não é um achado, é claro - tudo isso deveria ser conhecido há muito tempo, por aqueles que estão envolvidos no processamento de dados estatísticos aplicados e na otimização de quaisquer sistemas, não necessariamente especificamente do SGBD.
E: sim, eles sabem, escrevem artigos interessantes sobre suas pesquisas,
Por outro lado: de imediato não vejo qualquer menção ou divulgação generalizada desta abordagem na Internet entre especialistas em TI, DBA.
Então, direto ao ponto.
Suponhamos que temos uma tarefa: montar um determinado sistema de serviços para atender algum tipo de trabalho.
Sabe-se sobre este trabalho: o que é, como se mede a qualidade deste trabalho e qual o critério para medir essa qualidade.
Suponhamos também que seja mais ou menos conhecido e compreendido: exatamente como o trabalho é executado neste (ou com) este sistema de serviço.
“Mais ou menos” - significa que é possível preparar (ou obter de algum lugar) uma determinada ferramenta, utilidade, serviço que possa ser sintetizada e aplicada ao sistema com uma carga de testes suficientemente adequada ao que estará em produção, em condições suficientemente adequadas para trabalhar na produção.
Pois bem, vamos supor que seja conhecido um conjunto de parâmetros de ajuste para este sistema de serviço, que podem ser utilizados para configurar este sistema em termos da produtividade do seu trabalho.
E qual é o problema - não há uma compreensão suficientemente completa deste sistema de serviço, que permita definir habilmente as configurações deste sistema para carregamento futuro em uma determinada plataforma e obter a produtividade necessária do sistema.
Bem. Quase sempre é esse o caso.
O que você pode fazer aqui?
Bem, a primeira coisa que vem à mente é dar uma olhada na documentação deste sistema. Entenda quais são as faixas aceitáveis para os valores dos parâmetros de ajuste. E, por exemplo, usando o método de descida por coordenadas, selecione valores para parâmetros do sistema em testes.
Aqueles. dar ao sistema algum tipo de configuração, na forma de um conjunto específico de valores para seus parâmetros de configuração.
Aplique uma carga de teste a ele, usando este gerador de carga utilitário.
E observe o valor - a resposta ou uma métrica da qualidade do sistema.
O segundo pensamento pode ser a conclusão de que se trata de um período muito longo.
Bem, isto é: se houver muitos parâmetros de configuração, se os intervalos de seus valores executados forem grandes, se cada teste de carga individual levar muito tempo para ser concluído, então: sim, tudo isso pode levar um tempo inaceitável muito tempo.
Bem, aqui está o que você pode entender e lembrar.
Você pode descobrir que no conjunto de valores dos parâmetros de configuração do sistema de serviço existe um vetor, como uma sequência de alguns valores.
Cada um desses vetores, ceteris paribus (na medida em que não é afetado por esse vetor), corresponde a um valor completamente definido da métrica - um indicador da qualidade da operação do sistema sob uma carga de teste.
Ie
Vamos denotar o vetor de configuração do sistema como Onde ; Onde — número de parâmetros de configuração do sistema, quantos desses parâmetros existem.
E o valor da métrica correspondente a isso vamos denotá-lo como
, então obtemos uma função:
Pois bem: tudo se resume imediatamente, no meu caso: quase esquecido desde os tempos de estudante, algoritmos para busca do extremo de uma função.
Ok, mas aqui surge uma questão organizacional e aplicada: qual algoritmo usar.
- No sentido - para que você possa codificar menos manualmente.
- E para que funcione, ou seja, encontrou o extremo (se houver), bem, pelo menos mais rápido que a descida coordenada.
O primeiro ponto sugere que precisamos olhar para alguns ambientes nos quais tais algoritmos já foram implementados e estão, de alguma forma, prontos para uso em código.
Bem, eu sei python
и cran-r
O segundo ponto significa que você precisa ler sobre os próprios algoritmos, o que são, quais são seus requisitos e as características de seu trabalho.
E o que eles fornecem podem ser efeitos colaterais úteis - resultados ou diretamente do próprio algoritmo.
Ou podem ser obtidos a partir dos resultados do algoritmo.
Depende muito das condições de entrada.
Por exemplo, se, por algum motivo, você precisa obter um resultado mais rápido, bem, você precisa olhar para os algoritmos de gradiente descendente e escolher um deles.
Ou, se o tempo não for tão importante, você pode, por exemplo, usar métodos de otimização estocástica, como um algoritmo genético.
Proponho considerar o trabalho desta abordagem, selecionando a configuração do sistema, utilizando um algoritmo genético, no próximo, por assim dizer: trabalho de laboratório.
Fonte:
- Que haja, como sistema de serviço:
oracle xe 18c
- Deixe-o servir à atividade transacional e ao objetivo: obter o maior rendimento possível do subbanco de dados, em transações/s.
- As transações podem ser muito diferentes na natureza do trabalho com dados e no contexto do trabalho.
Vamos combinar que são transações que não processam uma grande quantidade de dados tabulares.
No sentido de que não geram mais dados de desfazer do que de refazer e não processam grandes porcentagens de linhas e tabelas grandes.
São transações que alteram uma linha em uma tabela mais ou menos grande, com um pequeno número de índices nesta tabela.
Nesta situação: a produtividade da subbase de dados para processamento de transações será, com ressalva, determinada pela qualidade do processamento da base de dados redox.
Isenção de responsabilidade - se falarmos especificamente sobre as configurações do subdb.
Porque, no caso geral, pode haver, por exemplo, bloqueios transacionais entre sessões SQL, devido ao desenho do trabalho do usuário com dados tabulares e/ou modelo tabular.
O que, claro, terá um efeito deprimente na métrica TPS e este será um fator exógeno, em relação ao subbanco de dados: bem, é assim que o modelo tabular foi desenhado e o trabalho com os dados nele contém que ocorrem bloqueios.
Portanto, para a pureza do experimento, excluiremos esse fator, e a seguir esclarecerei exatamente como.
- Vamos supor, para maior certeza, que 100% dos comandos SQL enviados ao banco de dados sejam comandos DML.
Deixe que as características do usuário que trabalha com o subbanco de dados sejam as mesmas nos testes.
A saber: o número de sessões skl, dados tabulares, como as sessões skl funcionam com eles. - Subd trabalha em
FORCE LOGGING
,ARCHIVELOG
modificações. O modo de banco de dados flashback está desativado, no nível subd. - Redo logs: localizados em um sistema de arquivos separado, em um “disco” separado;
O restante do componente físico do banco de dados: em outro sistema de arquivos separado, em um “disco” separado:
Mais detalhes sobre o dispositivo físico. componentes de banco de dados de laboratório
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
Inicialmente, sob essas condições de carregamento, eu queria usar a transação subd
Tem um recurso tão maravilhoso que citarei o autor:
No coração do SLOB está o “método SLOB”. O Método SLOB visa testar plataformas
sem contenção de aplicativos. Não é possível obter o desempenho máximo do hardware
usando o código do aplicativo que está, por exemplo, vinculado ao bloqueio do aplicativo ou até mesmo
compartilhando blocos do Oracle Database. É isso mesmo: há sobrecarga ao compartilhar dados
em blocos de dados! Mas o SLOB – em sua implantação padrão – é imune a tal contenção.
Esta declaração: corresponde, é.
É conveniente regular o grau de paralelismo das sessões cl, esta é a chave -t
inicie o utilitário runit.sh
de SLOB
A porcentagem de comandos DML é regulada, na quantidade de mensagens de texto que são enviadas ao subd, em cada sessão de texto, parâmetro UPDATE_PCT
Separadamente e muito convenientemente: SLOB
em si, antes e depois da sessão de carregamento - prepara um statspack, ou awr-snapshots (o que está definido para ser preparado).
No entanto, descobriu-se que SLOB
não oferece suporte a sessões SQL com duração inferior a 30 segundos.
Portanto, primeiro codifiquei minha própria versão operária e camponesa do carregador, e então ele permaneceu em operação.
Deixe-me esclarecer o que o carregador faz e como faz, para maior clareza.
Essencialmente, o carregador se parece com isto:
Código do trabalhador
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
Os trabalhadores são lançados desta forma:
Trabalhadores em execução
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
E as mesas para os trabalhadores são preparadas assim:
Criando tabelas
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"
Aqueles. Para cada trabalhador (praticamente: uma sessão SQL separada no banco de dados) é criada uma tabela separada, com a qual o trabalhador trabalha.
Isso garante a ausência de bloqueios transacionais entre sessões de trabalho.
Cada trabalhador: faz a mesma coisa, com a sua mesa, as mesas são todas iguais.
Todos os trabalhadores realizam trabalho pelo mesmo período de tempo.
Além disso, por um tempo suficiente para que, por exemplo, uma troca de log ocorresse definitivamente, e mais de uma vez.
Bem, consequentemente, surgiram custos e efeitos associados.
No meu caso, configurei a duração do trabalho dos trabalhadores em 8 minutos.
Um pedaço de relatório do statspack descrevendo a operação do subd sob carga
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
Voltando ao trabalho de laboratório.
Iremos, em igualdade de circunstâncias, variar os valores dos seguintes parâmetros da subbase de dados do laboratório:
- Tamanho dos grupos de logs do banco de dados. faixa de valores: [32, 1024] MB;
- Número de grupos de diários no banco de dados. faixa de valores: [2,32];
log_archive_max_processes
faixa de valores: [1,8];commit_logging
dois valores são permitidos:batch|immediate
;commit_wait
dois valores são permitidos:wait|nowait
;log_buffer
faixa de valores: [2,128] MB.log_checkpoint_timeout
faixa de valores: [60,1200] segundosdb_writer_processes
faixa de valores: [1,4]undo_retention
intervalo de valores: [30;300] segundostransactions_per_rollback_segment
faixa de valores: [1,8]disk_asynch_io
dois valores são permitidos:true|false
;filesystemio_options
os seguintes valores são permitidos:none|setall|directIO|asynch
;db_block_checking
os seguintes valores são permitidos:OFF|LOW|MEDIUM|FULL
;db_block_checksum
os seguintes valores são permitidos:OFF|TYPICAL|FULL
;
Uma pessoa com experiência em manutenção de bancos de dados Oracle certamente já pode dizer o que e para quais valores devem ser definidos, a partir dos parâmetros especificados e seus valores aceitáveis, a fim de obter maior produtividade do banco de dados para o trabalho com os dados que são indicados por o código do aplicativo, aqui acima.
Mas.
O objetivo do trabalho de laboratório é mostrar que o próprio algoritmo de otimização esclarecerá isso para nós de forma relativamente rápida.
Para nós, basta olhar para o documento, através do sistema customizável, apenas o suficiente para saber quais parâmetros alterar e em quais faixas.
E também: codifique o código que será usado para trabalhar com o sistema customizado do algoritmo de otimização selecionado.
Então, agora sobre o código.
falei acima sobre cran-r
, ou seja: todas as manipulações com o sistema customizado são orquestradas na forma de um script R.
A tarefa real, análise, seleção por valor métrico, vetores de estado do sistema: este é um pacote GA
(
O pacote, neste caso, não é muito adequado, no sentido de que espera que os vetores (cromossomos, se em termos do pacote) sejam especificados na forma de sequências de números com parte fracionária.
E meu vetor, a partir dos valores dos parâmetros de configuração: são 14 quantidades - inteiros e valores de string.
O problema, é claro, é facilmente evitado atribuindo alguns números específicos aos valores das strings.
Assim, no final, a parte principal do script R fica assim:
Ligue para 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
Aqui, com a ajuda lower
и upper
atributos de sub-rotina ga
essencialmente, é especificada uma área do espaço de busca, dentro da qual será realizada uma busca por tal vetor (ou vetores) para o qual será obtido o valor máximo da função de aptidão.
A sub-rotina ga realiza uma busca maximizando a função de aptidão.
Pois bem, verifica-se que, neste caso, é necessário que a função de aptidão, entendendo o vetor como um conjunto de valores para determinados parâmetros do subd, receba uma métrica do subd.
Ou seja: quantos, com uma determinada configuração de subd e uma determinada carga no subd: o subd processa transações por segundo.
Ou seja, ao desdobrar, as seguintes etapas múltiplas devem ser executadas dentro da função de fitness:
- Processando o vetor de entrada de números - convertendo-o em valores para os parâmetros de subdados.
- Uma tentativa de criar um determinado número de grupos de refazer de um determinado tamanho. Além disso, a tentativa pode não ter sucesso.
Grupos de revistas que já existiam no subd, em alguma quantidade e de algum tamanho, para a pureza do experimento - d.b. excluído. - Se o ponto anterior for bem sucedido: especificando os valores dos parâmetros de configuração para o banco de dados (novamente: pode haver uma falha)
- Se a etapa anterior for bem-sucedida: parar o subd, iniciar o subd para que os valores dos parâmetros recém-especificados tenham efeito. (novamente: pode haver uma falha)
- Se a etapa anterior for bem-sucedida: execute um teste de carga. obtenha métricas do subd.
- Retorne o subd ao seu estado original, ou seja, exclua grupos de log adicionais, retorne a configuração original do subbanco de dados para funcionar.
Código de função de condicionamento físico
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)
}
Que. todo trabalho: realizado na função fitness.
A sub-rotina ga processa vetores ou, mais corretamente, cromossomos.
Nesse caso, o que é mais importante para nós é a seleção de cromossomos com genes para os quais a função de aptidão produz grandes valores.
Este é, em essência, o processo de busca pelo conjunto ideal de cromossomos usando um vetor em um espaço de busca N-dimensional.
Muito claro, detalhado
Gostaria de observar separadamente dois pontos técnicos.
Chamadas auxiliares da função evaluate
, por exemplo, stop-start, definindo o valor do parâmetro subd, são executados com base em cran-r
funções system2
Com a ajuda de: algum script ou comando bash é chamado.
Por exemplo:
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)
}
}
O segundo ponto é a linha, evaluate
funções, salvando um valor de métrica específico e seu vetor de ajuste correspondente em um arquivo de log:
cat( paste("result: ",v_metric," ",v_vector,sep="") , file=v_logfile, sep="n", append=T)
Isso é importante, pois a partir dessa matriz de dados será possível obter informações adicionais sobre qual dos componentes do vetor de sintonia tem maior ou menor efeito no valor da métrica.
Ou seja: será possível realizar análises de importância de atributos.
Então, o que pode acontecer?
Em forma de gráfico, se você ordenar os testes em ordem métrica crescente, a imagem será a seguinte:
Alguns dados correspondentes aos valores extremos da métrica:
Aqui, na captura de tela com os resultados, vou esclarecer: os valores do vetor de ajuste são dados em termos do código da função de fitness, não em termos da lista numérica de parâmetros/intervalos de valores de parâmetros, que foi formulada acima no texto.
Bem. É muito ou pouco, ~8 mil tps: uma questão à parte.
No âmbito do trabalho de laboratório este valor não é importante, o que importa é a dinâmica, como este valor muda.
A dinâmica aqui é boa.
É óbvio que pelo menos um fator influencia significativamente o valor da métrica, o algoritmo ga, classificando os vetores cromossômicos: coberto.
A julgar pela dinâmica bastante vigorosa dos valores da curva, há pelo menos mais um fator que, embora significativamente menor, tem influência.
É aqui que você precisa attribute-importance
análise para entender quais atributos (bem, neste caso, componentes do vetor de ajuste) e o quanto eles influenciam o valor da métrica.
E a partir dessas informações: entenda quais fatores foram afetados pelas mudanças em atributos significativos.
corrida attribute-importance
possível de diferentes maneiras.
Para esses fins, gosto do algoritmo randomForest
Pacote R com o mesmo nome (
randomForest
, pelo que entendo seu trabalho em geral e sua abordagem para avaliar a importância dos atributos em particular, constrói um certo modelo de dependência da variável resposta dos atributos.
No nosso caso, a variável resposta é uma métrica obtida do banco de dados em testes de carga: tps
;
E os atributos são componentes do vetor de ajuste.
Então aqui randomForest
avalia a importância de cada atributo do modelo com dois números: %IncMSE
— como a presença/ausência deste atributo num modelo altera a qualidade do MSE deste modelo (Erro Quadrático Médio);
E IncNodePurity é um número que reflete o quão bem, com base nos valores deste atributo, um conjunto de dados com observações pode ser dividido, de modo que em uma parte haja dados com um valor da métrica que está sendo explicada, e na outra com outro valor da métrica.
Bem, isto é: até que ponto isso é um atributo de classificação (vi a explicação mais clara em russo no RandomForest
Código R do trabalhador-camponês para processar um conjunto de dados com os resultados dos testes de carga:
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
Você pode selecionar diretamente os hiperparâmetros do algoritmo com suas mãos e, focando na qualidade do modelo, selecionar um modelo que atenda com mais precisão às previsões no conjunto de dados de validação.
Você pode escrever algum tipo de função para este trabalho (aliás, novamente, usando algum tipo de algoritmo de otimização).
Você pode usar o pacote R caret
, não o ponto é importante.
Como resultado, neste caso, obtém-se o seguinte resultado para avaliar o grau de importância dos atributos:
Bem. Assim, podemos iniciar a reflexão global:
- Acontece que o mais significativo, sob estas condições de teste, foi o parâmetro
commit_wait
Tecnicamente, ele especifica o modo de execução da operação io de gravação de dados redo do buffer de log subdb para o grupo de log atual: síncrono ou assíncrono.
Valornowait
o que resulta em um aumento múltiplo quase vertical no valor da métrica tps: esta é a inclusão do modo io assíncrono em grupos de redo.
Uma outra questão é se você deve ou não fazer isso em um banco de dados de alimentos. Aqui me limito a apenas afirmar: este é um fator significativo. - É lógico que o tamanho do buffer de log do subd: seja um fator significativo.
Quanto menor o tamanho do buffer de log, menor sua capacidade de buffer, mais frequentemente ele transborda e/ou a incapacidade de alocar uma área livre nele para uma porção de novos dados redox.
Isso significa: atrasos associados à alocação de espaço no buffer de log e/ou ao despejo de dados de redo dele em grupos de redo.
Esses atrasos, é claro, deveriam afetar e afetam o rendimento do banco de dados para transações. - Parâmetro
db_block_checksum
: bem, também, em geral, é claro - o processamento de transações leva à formação de blocos darty no cache do buffer do subbanco de dados.
Que, quando a verificação de somas de verificação de blocos de dados está habilitada, o banco de dados deve processar - calcular essas somas de verificação a partir do corpo do bloco de dados, verificá-las com o que está escrito no cabeçalho do bloco de dados: corresponde/não corresponde.
Tal trabalho, novamente, não pode deixar de atrasar o processamento de dados e, consequentemente, o parâmetro e o mecanismo que define esse parâmetro revelam-se significativos.
É por isso que o fornecedor oferece, na documentação deste parâmetro, valores diferentes e observa que sim, haverá impacto, mas você pode escolher valores diferentes, até mesmo “off” e impactos diferentes.
Bem, uma conclusão global.
A abordagem, em geral, acaba funcionando bastante.
Ele se permite, nos estágios iniciais do teste de carga de um determinado sistema de serviço, selecionar sua configuração ideal (do sistema) para a carga, sem se aprofundar muito nas especificidades da configuração do sistema para a carga.
Mas não o exclui completamente - pelo menos no nível de compreensão: o sistema deve conhecer os “botões de ajuste” e as faixas de rotação permitidas desses botões.
A abordagem pode então encontrar com relativa rapidez a configuração ideal do sistema.
E com base nos resultados dos testes, é possível obter informações sobre a natureza da relação entre as métricas de desempenho do sistema e os valores dos parâmetros de configuração do sistema.
O que, claro, deve contribuir para o surgimento dessa compreensão muito profunda do sistema, do seu funcionamento, pelo menos sob uma determinada carga.
Na prática, trata-se de uma troca dos custos de compreensão do sistema customizado pelos custos de preparação de tais testes do sistema.
Gostaria de observar separadamente: nesta abordagem, o grau de adequação dos testes do sistema às condições operacionais que terá na operação comercial é extremamente importante.
Obrigado pela sua atenção e tempo.
Fonte: habr.com