Да измерим service time

 Общи  Коментарите са изключени за Да измерим service time
Авг. 252014
 

Да ни е честита новата чудесна система. Дадохме за нея една торба пари, инсталираме я от маса време. Ама как да проверим дали се държи адекватно? Дали всички конфигурации са наред, дали не сме забравили нещо? Дали няма да се срине при go live? Дали работи поне толкова добре токова добре като настоящата…

Тези въпроси ме тормозят с внедряването на новата ни ексадата. Промяната не е малка – хардуер, ОС, че и RAC на всичкото отгоре.

За щастие си имаме QA, които могат да пуснат автоматизирани тестове и да следим как работи. Обаче отговора „така като гледам, изглежда добре“ не ме радва. Иска да знам точно как се държи системата.

Ако сте се интересували от теорията на опашките (примерно покрай моята лекция на БГПО), помните че

Response Time = Service Time + Waiti time

Servce time е точно това, което ми трябва – то е функция на системата и настройките. Дяволията е да се измери service time с достатъчна точност. За това си копирахме една production база на новото желязо, пуснахме си тестовете и започнахме да смятаме. Автоматизирания тест може да симулира текущия Peak production load с разни варианти – примерно 0.25х, 0.5х, 1х, 2х, 4х и т.н. Напомням, че за да се смята чист service time, ни трявба минимален (по възможност никакъв) wait time. Това се получава при нисък arrival rate. Сега, не че не пуснахме и 16х, щото ни сърбяха ръцете (между другото, издържахме го, но response time беше около 5х service time). Обаче за измерване на чистия service time пускахме 0.25х и 0.5х.

Ситуацията е следната: пускаме натоварването да върви известно време. Примерно правим някокло десетки хиляди плащания. Еталонно натоварване, повтаряемо. После замерваме DB time и делим времето на броя плащания. Така получаваме колко време се губи в БД за една бизнес транзакция, едно плащане. За удобство от време на време правим AWR snapshot. После ще ни трябва, за да установим натоварването.

Заявката се оказа по-корава, от колкото очаквах. Но в крайна сметка успях да установя средния db time per buiness transaction за всеки един AWR snapshot така:

select begin_interval_time, end_interval_time, trns, db_time_msec,
       decode(trns, 0, 0, db_time_msec / trns) msec_db_time_per_pay
  from (select m.snap_id, begin_interval_time, end_interval_time, m.dbid,
                (select count(1)
                    from -- your table with with business transactions goes here
                   where transaction_begin_time >= begin_interval_time -- get the number of transaction within the snapshot
                     and transaction_begin_time < end_interval_time) trns, 
								db_time_msec
           from dba_hist_snapshot s,
                (select snap_id, dbid, sum(db_time) / 1000 db_time_msec
                    from (select snap_id, dbid,
                                  value - lag(value, 1) over(partition by instance_number order by snap_id) db_time
                             from DBA_HIST_SYS_TIME_MODEL m
                            where stat_name = 'DB time')
                   group by snap_id, dbid) m
          where begin_interval_time > trunc(sysdate) -- take all snapshots for today
            and instance_number = 2 -- we want to take one row per snapshot, so we pick some instance. we aggregate the data from all instances later
            and m.snap_id = s.snap_id
            and m.dbid = s.dbid)
 order by 1

Така. Понеже знам, че на тази БД няма никакаво друго натоварване, си позволявам да взема целия DB time. Което не е много честно ако върви и нещо в паралел с нашия тест.

Това се забеляза болезнено когато решихме да замерим времето и на текущата production система. Понеже там освен нашия тест върви и реалния трафик, който е абсолютно разнороден (не само транзакции), се получават едни странни цифри. Така че за замерване на production направихме следното
– замерването го правим с 0.25x peak load
теста се пуска по време с ниско натоварване (при нас това е рано сутрин), за да няма много wait time
– направихме си един отделен service, на който да закачим тестовия application. Така можем да отделим натоварването от теста от всичките други неща които се случват в една production база
– разбира се, AWR репорти преди и след (и по време на) теста са задължителни

За измерване на db time вече не може да използваме DBA_HIST_SYS_TIME_MODEL. Но Oracle, в тяхната безкрайна мъдрост, са ни предоставили и DBA_HIST_SERVICE_STAT – същата статистика, разбита по service

select begin_interval_time, end_interval_time, trns, db_time_msec,
       decode(trns, 0, 0, db_time_msec / trns) msec_db_time_per_pay
  from (select m.snap_id, begin_interval_time, end_interval_time, m.dbid,
                (select count(1)
                    from -- your table with with business transactions goes here
                   where transaction_begin_time >= begin_interval_time -- get the number of transaction within the snapshot
                     and transaction_begin_time < end_interval_time
                     and ... -- make sure you take only the test transactions - you need some way to mark those in the application
										 ) trns, db_time_msec
           from dba_hist_snapshot s,
                (select snap_id, dbid, sum(db_time) / 1000 db_time_msec
                    from (select instance_number, sn.dbid, ss.snap_id, ss.value,
                                  ss.value - lag(ss.value, 1) over(partition by instance_number, sn.service_name order by snap_id) db_time
                             from DBA_HIST_SERVICE_NAME sn, DBA_HIST_SERVICE_STAT ss
                            where sn.dbid = ss.dbid
                              and sn.service_name_hash = ss.service_name_hash
                              and sn.service_name in (/*[your test service name goes here]*/)
                              and ss.stat_name = 'DB time')
                   group by snap_id, dbid) m
          where begin_interval_time > trunc(sysdate) -- take all snapshots for today
            and instance_number = 1 -- we want to take one row per snapshot, so we pick some instance. we aggregate the data from all instances later
            and m.snap_id = s.snap_id
            and m.dbid = s.dbid)
 order by 1
 Posted by at 16:36