Методът на научното мушкане или как да изберете конфигурация на база данни с помощта на бенчмаркове и алгоритъм за оптимизация

Здравейте

Реших да споделя моята находка - плод на размисъл, проба-грешка.
Като цяло: това не е находка, разбира се - всичко това трябваше да е известно отдавна на тези, които се занимават с приложна статистическа обработка на данни и оптимизация на всякакви системи, не непременно конкретно на СУБД.
И: да, те знаят, те пишат интересни статии за своите изследвания, пример (UPD.: в коментарите те посочиха много интересен проект: ottertune )
От друга страна: на пръв поглед не виждам широко споменаване или разпространение на този подход в Интернет сред ИТ специалистите, DBA.

И така, към точката.

Да приемем, че имаме задача: да настроим определена система за обслужване, която да обслужва някакъв вид работа.

За тази работа се знае: какво представлява, как се измерва качеството на тази работа и какъв е критерият за измерване на това качество.

Нека също така приемем, че е повече или по-малко известно и разбрано: как точно се извършва работата в (или с) тази сервизна система.

„Повече или по-малко“ - това означава, че е възможно да се подготви (или да се вземе от някъде) определен инструмент, помощна програма, услуга, която може да бъде синтезирана и приложена към системата с тестово натоварване, достатъчно адекватно на това, което ще бъде в производството, в условия, достатъчно подходящи за работа в производството.

Е, нека приемем, че е известен набор от параметри за настройка за тази сервизна система, които могат да се използват за конфигуриране на тази система по отношение на производителността на нейната работа.

И какъв е проблемът - няма достатъчно пълно разбиране на тази сервизна система, което да ви позволява експертно да конфигурирате настройките на тази система за бъдещо натоварване на дадена платформа и да получите необходимата производителност на системата.

Добре. Почти винаги е така.

Какво можете да правите тук?

Е, първото нещо, което идва на ум, е да погледнете документацията за тази система. Разберете какви са приемливите диапазони за стойностите на параметрите за настройка. И например, използвайки метода на спускане на координати, изберете стойности за системни параметри в тестове.

Тези. дайте на системата някаква конфигурация под формата на специфичен набор от стойности за нейните конфигурационни параметри.

Приложете тестово натоварване към него, като използвате точно този помощен инструмент, генератор на натоварване.
И вижте стойността - реакцията или показател за качеството на системата.

Втората мисъл може да бъде заключението, че това е много дълго време.

Ами, това е: ако има много параметри за настройка, ако диапазоните на техните стойности, които се изпълняват, са големи, ако всеки отделен тест за натоварване отнема много време, за да завърши, тогава: да, всичко това може да отнеме неприемливо дълго време.

Е, ето какво можете да разберете и запомните.

Можете да разберете, че в набора от стойности на параметрите на настройките на системата за обслужване има вектор, като последователност от някои стойности.

Всеки такъв вектор, при равни други условия (в това, че не се влияе от този вектор), съответства на напълно определена стойност на метриката - показател за качеството на работата на системата при тестово натоварване.

Т.е.

Нека обозначим вектора на системната конфигурация като Методът на научното мушкане или как да изберете конфигурация на база данни с помощта на бенчмаркове и алгоритъм за оптимизацияКъдето Методът на научното мушкане или как да изберете конфигурация на база данни с помощта на бенчмаркове и алгоритъм за оптимизация; Където Методът на научното мушкане или как да изберете конфигурация на база данни с помощта на бенчмаркове и алгоритъм за оптимизация — брой на системните конфигурационни параметри, колко от тези параметри има.

И стойността на показателя, съответстваща на това Методът на научното мушкане или как да изберете конфигурация на база данни с помощта на бенчмаркове и алгоритъм за оптимизация нека го обозначим като
Методът на научното мушкане или как да изберете конфигурация на база данни с помощта на бенчмаркове и алгоритъм за оптимизация, тогава получаваме функция: Методът на научното мушкане или как да изберете конфигурация на база данни с помощта на бенчмаркове и алгоритъм за оптимизация

Е, тогава всичко веднага се свежда до, в моя случай, почти забравени от студентските години алгоритми за търсене на екстремума на функция.

Добре, но тук възниква един организационен и приложен въпрос: кой алгоритъм да използвам.

  1. В смисъл - за да кодирате по-малко на ръка.
  2. И за да работи, т.е. намери екстремума (ако има такъв), добре, поне по-бързо от координатното спускане.

Първата точка подсказва, че трябва да погледнем към някои среди, в които такива алгоритми вече са внедрени и под някаква форма са готови за използване в код.
Е, знам python и cran-r

Втората точка означава, че трябва да прочетете за самите алгоритми, какви са те, какви са техните изисквания и характеристиките на тяхната работа.

И това, което дават може да са полезни странични ефекти - резултати, или директно от самия алгоритъм.

Или могат да бъдат получени от резултатите на алгоритъма.

Много зависи от входните условия.

Например, ако по някаква причина трябва да получите резултат по-бързо, добре, трябва да погледнете към алгоритмите за градиентно спускане и да изберете един от тях.

Или, ако времето не е толкова важно, можете например да използвате методи за стохастична оптимизация, като например генетичен алгоритъм.

Предлагам да разгледаме работата на този подход, избирайки конфигурацията на системата, използвайки генетичен алгоритъм, в следващата, така да се каже: лабораторна работа.

оригинал:

  1. Нека има, като система за обслужване: oracle xe 18c
  2. Нека обслужва транзакционната дейност и целта: да се получи възможно най-високата производителност на подбазата данни в транзакции/сек.
  3. Транзакциите могат да бъдат много различни по естеството на работа с данни и контекста на работата.
    Нека се съгласим, че това са транзакции, които не обработват голямо количество таблични данни.
    В смисъл, че не генерират повече данни за отмяна, отколкото за повторение и не обработват големи проценти от редове и големи таблици.

Това са транзакции, които променят един ред в повече или по-малко голяма таблица, с малък брой индекси в тази таблица.

В тази ситуация: производителността на подбазата данни за обработка на транзакции, с уговорка, ще се определя от качеството на обработка от редокс базата данни.

Отказ от отговорност - ако говорим конкретно за настройките на subdb.

Тъй като в общия случай може да има, например, блокиране на транзакции между SQL сесии, поради дизайна на работата на потребителя с таблични данни и/или табличния модел.

Което, разбира се, ще има депресиращ ефект върху метриката на TPS и това ще бъде екзогенен фактор по отношение на подбазата данни: добре, така е проектиран табличният модел и работата с данни в него, че възникват блокажи.

Затова за чистотата на експеримента ще изключим този фактор, като по-долу ще изясня как точно.

  1. Нека приемем за категоричност, че 100% от SQL командите, подадени към базата данни, са DML команди.
    Нека характеристиките на работата на потребителя с подбазата данни са същите в тестовете.
    А именно: броя на skl сесиите, таблични данни, как skl сесиите работят с тях.
  2. Subd работи в FORCE LOGGING, ARCHIVELOG модове. Режимът Flashback-база данни е изключен на ниво subd.
  3. Redo logs: разположени в отделна файлова система, на отделен “диск”;
    Останалата част от физическия компонент на базата данни: в друга, отделна файлова система, на отделен „диск“:

Повече подробности за физическото устройство. компоненти на лабораторни бази данни

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

Първоначално, при тези условия на натоварване, исках да използвам транзакция subd SLOB-полезност
Има толкова чудесна функция, ще цитирам автора:

В основата на SLOB е „SLOB методът“. Методът SLOB има за цел да тества платформи
без спор за кандидатстване. Човек не може да постигне максимална хардуерна производителност
използвайки код на приложение, който е например обвързан от заключване на приложение или дори
споделяне на блокове от Oracle Database. Точно така – има режийни разходи при споделяне на данни
в блокове с данни! Но SLOB – в неговото внедряване по подразбиране – е имунизиран срещу подобни спорове.

Тази декларация: съответства, тя е.
Удобно е да регулирате степента на паралелност на cl сесиите, това е ключът -t стартирайте помощната програма runit.sh от SLOB
Процентът на DML командите се регулира в броя на текстовите съобщения, които се изпращат до subd, всяка текстова сесия, параметър UPDATE_PCT
Отделно и много удобно: SLOB себе си, преди и след сесията за зареждане - подготвя statspack или awr-snapshots (какво е зададено да се подготви).

Оказа се обаче, че SLOB не поддържа SQL сесии с продължителност под 30 секунди.
Затова първо кодирах моя собствена, работническо-селска версия на товарача и след това остана в експлоатация.

Нека изясня какво прави товарачът и как го прави, за по-голяма яснота.
По същество товарачът изглежда така:

Код на работника

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

Работниците се стартират по следния начин:

Работещи работници

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

И масите за работниците се подготвят така:

Създаване на таблици

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"

Тези. За всеки worker (на практика: отделна SQL сесия в БД) се създава отделна таблица, с която работи worker-а.

Това гарантира липсата на транзакционни заключвания между работните сесии.
Всеки работник: прави едно и също нещо, със собствената си маса, масите са еднакви.
Всички работници извършват работа за еднакво време.
Освен това за достатъчно дълго време, така че например определено да се случи превключване на журнала и то повече от веднъж.
Е, съответно, възникнаха свързани разходи и ефекти.
В моя случай конфигурирах продължителността на работата на работниците на 8 минути.

Част от доклада на statspack, описващ работата на subd под натоварване

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

Връщане към лабораторната работа.
Ние, при равни други условия, ще променяме стойностите на следните параметри на лабораторната подбаза данни:

  1. Размер на групите от регистрационни файлове на базата данни. диапазон на стойността: [32, 1024] MB;
  2. Брой журнални групи в базата данни. диапазон на стойността: [2,32];
  3. log_archive_max_processes диапазон на стойността: [1,8];
  4. commit_logging разрешени са две стойности: batch|immediate;
  5. commit_wait разрешени са две стойности: wait|nowait;
  6. log_buffer диапазон на стойността: [2,128] MB.
  7. log_checkpoint_timeout диапазон на стойността: [60,1200] секунди
  8. db_writer_processes диапазон на стойността: [1,4]
  9. undo_retention диапазон на стойността: [30;300] секунди
  10. transactions_per_rollback_segment диапазон на стойността: [1,8]
  11. disk_asynch_io разрешени са две стойности: true|false;
  12. filesystemio_options разрешени са следните стойности: none|setall|directIO|asynch;
  13. db_block_checking разрешени са следните стойности: OFF|LOW|MEDIUM|FULL;
  14. db_block_checksum разрешени са следните стойности: OFF|TYPICAL|FULL;

Човек с опит в поддържането на бази данни на Oracle със сигурност вече може да каже какво и на какви стойности трябва да се зададат, от посочените параметри и техните допустими стойности, за да се получи по-голяма производителност на базата данни за работа с данни, които са посочени от кода на приложението тук по-горе.

Но.

Смисълът на лабораторната работа е да покаже, че самият алгоритъм за оптимизация ще ни изясни това относително бързо.

За нас остава само да надникнем в документа през персонализираната система, колкото да разберем какви параметри да променим и в какви граници.
И също така: кодирайте кода, който ще се използва за работа с персонализираната система на избрания алгоритъм за оптимизация.

И така, сега за кода.
Говорих по-горе за cran-r, т.е.: всички манипулации с персонализираната система са оркестрирани под формата на R скрипт.

Действителната задача, анализ, избор по метрична стойност, вектори на състоянието на системата: това е пакет GA (документация)
Пакетът в този случай не е много подходящ, в смисъл че очаква векторите (хромозомите, ако се отнася до пакета) да бъдат посочени под формата на низове от числа с дробна част.

И моят вектор, от стойностите на параметрите за настройка: това са 14 количества - цели числа и низови стойности.

Проблемът, разбира се, лесно се избягва чрез присвояване на някои специфични числа на низови стойности.

Така в крайна сметка основната част от R скрипта изглежда така:

Обадете се на 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

Тук, с помощта lower и upper атрибути на подпрограмата ga по същество е посочена област от пространството за търсене, в която ще се извърши търсене за такъв вектор (или вектори), за които ще бъде получена максималната стойност на функцията за годност.

Подпрограмата ga извършва търсене, като максимизира функцията за годност.

Е, тогава се оказва, че в този случай е необходимо фитнес функцията, разбирайки вектора като набор от стойности за определени параметри на subd, да получи метрика от subd.

Тоест: колко, с дадена настройка на subd и дадено натоварване на subd: subd обработва транзакции за секунда.

Тоест, когато се разгъва, трябва да се извърши следната многоетапна стъпка във фитнес функцията:

  1. Обработка на входния вектор от числа - преобразуването му в стойности за параметрите на подданните.
  2. Опит за създаване на определен брой групи за повторение с даден размер. Освен това опитът може да се окаже неуспешен.
    Групи от списания, които вече съществуват в субд, в известно количество и с определен размер, за чистотата на експеримента - d.b. изтрити.
  3. Ако предишната точка е успешна: посочване на стойностите на конфигурационните параметри към базата данни (отново: може да има грешка)
  4. Ако предишната стъпка е успешна: спиране на subd, стартиране на subd, така че новопосочените стойности на параметрите да влязат в сила. (отново: може да има проблем)
  5. Ако предишната стъпка е успешна: извършете тест за натоварване. вземете показатели от подп.
  6. Върнете subd в първоначалното му състояние, т.е. изтриване на допълнителни журнални групи, връщане на оригиналната конфигурация на подбаза данни за работа.

Код на фитнес функция

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

Че. цялата работа: извършена във фитнес функцията.

Ga-подпрограмата обработва вектори или, по-правилно, хромозоми.
В което това, което е най-важно за нас, е селекцията на хромозоми с гени, за които фитнес функцията произвежда големи стойности.

Това по същество е процесът на търсене на оптималния набор от хромозоми с помощта на вектор в N-измерно пространство за търсене.

Много ясно, подробно обяснение, с примери за R-код, работата на генетичен алгоритъм.

Бих искал отделно да отбележа две технически точки.

Спомагателни извиквания от функцията evaluate, например, стоп-старт, задаване на стойността на параметъра subd, се извършват въз основа на cran-r функции system2

С помощта на което: се извиква някакъв bash скрипт или команда.

Например:

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

Втората точка е линията, evaluate функции със запазване на конкретна метрична стойност и съответния вектор за настройка в лог файл:

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

Това е важно, тъй като от този масив от данни ще бъде възможно да се получи допълнителна информация за това кой от компонентите на вектора за настройка има по-голям или по-малък ефект върху метричната стойност.

Тоест: ще бъде възможно да се извърши анализ на атрибут-импорт.

И така, какво може да се случи?

В графична форма, ако подредите тестовете във възходящ метричен ред, картината е следната:

Методът на научното мушкане или как да изберете конфигурация на база данни с помощта на бенчмаркове и алгоритъм за оптимизация

Някои данни, съответстващи на екстремните стойности на показателя:
Методът на научното мушкане или как да изберете конфигурация на база данни с помощта на бенчмаркове и алгоритъм за оптимизация
Тук, в екранната снимка с резултатите, ще изясня: стойностите на вектора за настройка са дадени от гледна точка на кода на фитнес функцията, а не от гледна точка на числовия списък от параметри/диапазони от стойности на параметри, който беше формулиран по-горе в текста.

Добре. Много ли е или малко, ~8 хиляди tps: отделен въпрос.
В рамките на лабораторната работа тази цифра не е важна, важна е динамиката, как се променя тази стойност.

Динамиката тук е добра.
Очевидно е, че поне един фактор значително влияе върху стойността на показателя, ga-алгоритъмът, сортиращ през хромозомните вектори: покрит.
Съдейки по доста бурната динамика на стойностите на кривата, има поне още един фактор, който, макар и значително по-малък, оказва влияние.

Това е мястото, където имате нужда от него attribute-importance анализ, за ​​да разберете какви атрибути (добре, в този случай, компоненти на вектора за настройка) и доколко те влияят на метричната стойност.
И от тази информация: разберете кои фактори са били повлияни от промените в значимите атрибути.

Изпълни attribute-importance възможни по различни начини.

За тези цели ми харесва алгоритъма randomForest R пакет със същото име (документация)
randomForest, както разбирам работата му като цяло и неговия подход към оценката на важността на атрибутите в частност, изгражда определен модел на зависимостта на променливата на отговора от атрибутите.

В нашия случай променливата за отговор е метрика, получена от базата данни при тестове за натоварване: tps;
А атрибутите са компоненти на вектора за настройка.

Така че тук randomForest оценява важността на всеки атрибут на модела с две числа: %IncMSE — как наличието/отсъствието на този атрибут в модел променя качеството на MSE на този модел (средна квадратична грешка);

А IncNodePurity е число, което отразява колко добре въз основа на стойностите на този атрибут може да бъде разделен набор от данни с наблюдения, така че в едната част да има данни с една стойност на обяснявания показател, а в другата с друга стойност на показателя.
Е, това е: до каква степен това е класифициращ атрибут (видях най-ясното обяснение на руски език в RandomForest тук).

Работническо-селски R-код за обработка на набор от данни с резултатите от тестовете за натоварване:

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

Можете директно да изберете хиперпараметрите на алгоритъма с ръцете си и, като се фокусирате върху качеството на модела, изберете модел, който по-точно изпълнява прогнозите на набора от данни за валидиране.
Можете да напишете някаква функция за тази работа (между другото, отново, като използвате някакъв алгоритъм за оптимизация).

Можете да използвате R пакет caret, не точката е важна.

В резултат на това в този случай се получава следният резултат за оценка на степента на важност на атрибутите:

Методът на научното мушкане или как да изберете конфигурация на база данни с помощта на бенчмаркове и алгоритъм за оптимизация

Добре. Така можем да започнем глобално отражение:

  1. Оказва се, че най-значимият при тези условия на тестване е параметърът commit_wait
    Технически, той определя режима на изпълнение на операцията io за записване на повторни данни от буфера на регистрационния файл на subdb в текущата група регистрационни файлове: синхронен или асинхронен.
    Стойност nowait което води до почти вертикално, многократно увеличение на стойността на показателя tps: това е включването на асинхронния io режим в групите за повторение.
    Отделен въпрос е дали трябва или не трябва да правите това в хранителна база данни. Тук се ограничавам само да заявя: това е важен фактор.
  2. Логично е размерът на лог буфера на subd: да се окаже важен фактор.
    Колкото по-малък е размерът на регистрационния буфер, толкова по-малък е неговият буферен капацитет, толкова по-често се препълва и/или невъзможността да се разпредели свободна област в него за част от новите редокс данни.
    Това означава: закъснения, свързани с разпределянето на пространство в буфера на журнала и/или изхвърлянето на данни за повторение от него в групи за повторение.
    Тези закъснения, разбира се, трябва и влияят на пропускателната способност на базата данни за транзакции.
  3. Параметър db_block_checksum: добре, също като цяло е ясно - обработката на транзакция води до формирането на блокове Darty в буферния кеш на подбазата данни.
    Което, когато проверката на контролни суми на блокове данни е активирана, базата данни трябва да обработи - да изчисли тези контролни суми от тялото на блока данни, да ги провери с това, което е написано в заглавката на блока данни: съвпада/не съвпада.
    Такава работа отново не може да не забави обработката на данни и съответно параметърът и механизмът, който задава този параметър, се оказват значими.
    Ето защо продавачът предлага в документацията за този параметър различни стойности за него (параметъра) и отбелязва, че да, ще има влияние, но, добре, можете да изберете различни стойности, до „изключено“ и различни въздействия.

Е, глобален извод.

Подходът като цяло се оказва доста работещ.

Той напълно си позволява в ранните етапи на тестване на натоварването на определена сервизна система, за да избере нейната (системна) оптимална конфигурация за натоварване, да не се задълбочава твърде много в спецификата на настройка на системата за натоварване.

Но не го изключва напълно - поне на нивото на разбиране: системата трябва да знае за "регулиращите копчета" и допустимите диапазони на въртене на тези копчета.

След това подходът може относително бързо да намери оптималната системна конфигурация.
И въз основа на резултатите от тестването е възможно да се получи информация за естеството на връзката между показателите за производителност на системата и стойностите на параметрите на системните настройки.

Което, разбира се, трябва да допринесе за появата на това много дълбоко разбиране на системата, нейното функциониране, поне при дадено натоварване.

На практика това е размяна на разходите за разбиране на персонализираната система за разходите за подготовка на такова тестване на системата.

Бих искал да отбележа отделно: при този подход степента на адекватност на тестването на системата към условията на работа, които ще има при търговска експлоатация, е критично важна.

Благодаря ви за вниманието и отделеното време.

Източник: www.habr.com

Добавяне на нов коментар