Pages

29 Şubat 2012 Çarşamba

Ortalama aktif oturumlar(Average Active Sessions - AAS) ile ani yüklerin zaman aralıklarının bulunması

“Ortalama Aktif Oturumlar”(Average Active Session - AAS) metriği, Oracle veritabanının tüm  çalışma performansının ölçümünde olağandışı bir şekilde basit ve bir o kadar kullanışlı şekilde hizmet sunmaktadır.  AAS metriği, kısaca “DB Time” değerinin “işlem süresi-elapsed time” değerine bölünmesiyle tanımlanmaktadır.

Sırayla, “DB Time”, hem CPU üzerinde hemde boşta olmayan bekleme durumlarında sıkışmış tüm oturumlar tarafından harcanan zaman olarak tanımlanmaktadır. Diğer bir deyişle, “DB Time” tüm aktif oturumlar tarafından harcanan zamanların toplamı olarakta düşünülebilir.

Mesela, bir dakikalık gözlem süresince aktif olan dört oturum olduğunu düşünelim. Her bir oturum toplamda dört dakikalık “DB Time” değerini vercek şekilde numeratörde birer dakikalık toplam  “DB Time” değerine karşılık gelecektir. Bu örnekte, “geçen süre”  paydası bir dakikadır. Her iki değerin bölümü AAS değeri olarak 4 sonucunu vermektedir. Bu örnektende görüldüğü gibi, 4 AAS metriği 4 aktif oturuma sahip olmaya karşılık gelmektedir. Bu örnekte, ortalama olarak dört aktif oturum bulunmaktadır.

Eğer bu örneği çeşitli dönemlerde aktif durumda olan daha fazla oturum ilave ederek genelleştirirsek, AAS metriğinin hesaplaması gözlem periyodu süresince hala ortalama sayıda aktif  oturumlar hakkında bir fikir verecektir. 

AAS metriği CPU sayısı ile kıyaslandığında oldukça kullanışlı olmaktadır.  Eğer AAS metriği CPU sayısını çok aşarsa, bu durumda veritabanı performansı zarar görecektir. Öte yandan, eğer AAS metriği belirgin şekilde CPU sayısından düşükse, o zaman veritabanı performansı iyi olacaktır. Veritabanı perfomansını sekteye uğratan üst sınırdaki AAS metriğinin eşikdeğeri, uygulamanın davranışına ve son kullanıcıların beklentilerine bağlıdır. Bu yüzden, bu eşikdeğeri uygulama bağlamında belirlenmelidir. AAS eşikdeğeri belirlendiğinde, bu metrik oldukça güvenilir, hazır biçimde bütün veritabanı performans sorunlarının teşhisinde hizmet verecektir. Aslında, “DB Time“ metriğinin düşürülmesi Oracle ADDM iyileştirme aracının yegane hedefi olmaktadır.

Bu AAS metriği tam olarak eksiksiz hesaplanmalı, veya aşağıda belirtileceği gibi tahmin edilmelidir. Bütün metotlar, hem tahminleri kullanarak hemde kesin hesaplamaları kullanarak, “işlem süresi” paydasınının seçimine bağlı olmaktadır. 

İşlem süresi paydası ve anti homojenlik
AAS doğal bir kümedir veya ortalama bir metriktir. Ortalama tabanlı metrikler, temel verinin homojen olmayan durumunu her zaman gizlerler. Sıklıkla, bu gizli anti-homojenlik aslında Oracle performans probleminin anlaşılmasında en önemli bilgi kaynağı olmaktadır. İşte bu sebeple metriğin etkili kullanımı, anti-homojenliğin tespitini ve anlaşılmasını gerektirmektedir.

Bazı Oracle uzmanları, homojen olmayan herhangi bir tipi adlandırmak için “eğrilik-skew” tanımı kullanmaktadır.  Eğriliğin istatistiksel tanımı, aslında belirli bir tip anti-homojenlik ile sınırlandırılmıştır.

Aşağıdaki örneklerde de görüleceği üzere, “işlem süresi” paydası eğriliğin tespitinde çok önemlidir.  Daha geniş “işlem süresi” (mesela bir saat), nispeten birkaç satıra bakılması gerekeceğinden kullanım için daha uygundur. Ayrıca, saatlik ortalama pek çok uygulama ve çalışma için daha uygun olabilir. Ancak, daha düşük “işlem süresi” (mesela bir dakika), kısa anlık tepkilerin açığa çıkarılmasında faydalı olabilmektedir, ancak bu da yoğun bir veri hacmi oluşturacaktır. En iyi yaklaşım, kolaylık için mümkünse daha geniş “işlem süresi” kullanmak, ancak kısa anlık tepkilerin açığa çıkarılması gerektiği durumalarda ise daha kısa “işlem süresi” metriklerinin kullanılmasıdır.

ASH raporlarını kullanarak AAS tahmin metotları
AWR verisinden AAS metirklerini tahmin etmek için metodu belirleme noktasında kullanılan mantık ve matematik sırasıyla artalan biçimde aşağıdaki adımlarda yer almaktadır.

Adım 1 – Her bir gözlem için aktif oturum hesabı
Oracle, aktif oturumlar için temel durumları saniyede birkez kaydeder ve gözlemlerinin geçmiş bilgilerini V$ACTIVE_SESSION_HISTORY sistem tablosunda saklar. Her bir gözlem örneği SAMPLE_ID kolonu tarafından belirlenir. Verilen SAMPLE_ID için bu tablodaki satır sayısı, esasen bu gözlem için aktif oturum miktarıdır. Aşağıdaki örnek, her bir ASH gözlemi için 2 den 12 ye kadar aktif oturumların miktarını sorgu sonucu olarak getirmektedir.  

AAS tahmini için gerekmemesine rağmen, aşağıdaki sorgu, CPU üzerinde olduğunu düşündüğü bekleme durumundaki oturumları birbirinden ayırmaktadır. Bu ilave analiz sıklıkla faydalıdır, ancak gereklide değildir.  

select
   sample_id,
   sample_time,
   sum(decode(session_state, 'ON CPU', 1, 0))  as on_cpu,
   sum(decode(session_state, 'WAITING', 1, 0)) as waiting,
   count(*) as active_sessions
from
   v$active_session_history
where
   -- en son 15 saniye
   sample_time > sysdate - (0.25/1440)
group by
   sample_id,
   sample_time
order by
   sample_id;

 SAMPLE_ID SAMPLE_TIME                   ON_CPU    WAITING ACTIVE_SESSIONS
---------- ------------------------- ---------- ---------- ---------------
  25325213 24-NOV-11 15.32.03.078 PM          3          9              12
  25325214 24-NOV-11 15.32.04.085 PM          1          6               7
  25325215 24-NOV-11 15.32.05.095 PM          0          4               4
  25325216 24-NOV-11 15.32.06.105 PM          1          2               3
  25325217 24-NOV-11 15.32.07.115 PM          0          3               3
  25325218 24-NOV-11 15.32.08.125 PM          0          2               2
  25325219 24-NOV-11 15.32.09.135 PM          3          1               4
  25325220 24-NOV-11 15.32.10.155 PM          0          4               4
  25325221 24-NOV-11 15.32.11.165 PM          1          2               3
  25325222 24-NOV-11 15.32.12.175 PM          0          4               4
  25325223 24-NOV-11 15.32.13.185 PM          1          2               3
  25325224 24-NOV-11 15.32.14.195 PM          1          3               4
  25325225 24-NOV-11 15.32.15.205 PM          1          4               5
  25325226 24-NOV-11 15.32.16.215 PM          1          2               3
 
14 rows selected.

Bunu bir kenara bırakırsak, aktif bir oturumun ASH tanımının V$SESSION_STATE görünümü değeri ile tam olarak eşleşmesi çokta gerekli değildir. Ayrıca, bazen ASH “idle” bekleme durumundaki oturumları, aktif olacaklarını normalde beklemesekte, kaydeder. Ancak, hiçbir ikincil düşünce bu yaklaşımın gereksiz olduğunu pekiştirmez.

Adım 2 – Bir zaman aralığı boyunca aktif oturum sayısını bulmak
Adım 1’deki sorguda, belirli zaman aralığında ASH tarafından kayıt edilen herbir gözlem için oturumların sayısı tespit edildi. Aktif oturumların ortalama sayısını hesaplamak için Adım 1’deki sorguyu bir satır içi görününüm ile altsorguya dönüştürüp, ortalamasını alacak bir  dış sorgu ile saracağız. Bu örnekte, ortalamaları tekli ondalığa yuvarlayacak ve ortalamaları altsorgudaki en erken zaman mühürü ile ilişkilendireceğim.

select
   to_char(min(sub1.sample_time), 'YYYY-MM-DD HH24:MI:SS') as sample_time,
   round(avg(sub1.on_cpu),1) as cpu_avg,
   round(avg(sub1.waiting),1) as wait_avg,
   round(avg(sub1.active_sessions),1) as act_avg
from
   ( -- altsorgu 1: saniye başı bir satır, SAMPLE_TIME çözümü
     select
        sample_id,
        sample_time,
        sum(decode(session_state, 'ON CPU', 1, 0))  as on_cpu,
        sum(decode(session_state, 'WAITING', 1, 0)) as waiting,
        count(*) as active_sessions
     from
        v$active_session_history
     where
        sample_time > sysdate - (0.25/1440)
     group by
        sample_id,
        sample_time
   ) sub1;

SAMPLE_TIME            CPU_AVG   WAIT_AVG    ACT_AVG
------------------- ---------- ---------- ----------
2011-11-24 15:45:30        .7        2.8        3.8

1 row selected.

Yukarıdaki sorgu sonucu ortalaması veritabanı boştayken çekilen ASH snapshotlarından herhangi bir veri içermemektedir.  ASH aktif olmayan oturumlar olarak bulunan gözlemler için bir satır kaydetmez.  Bu yüzden, bu şekilde hesaplanan ortalamalar, aktif oturumlar olmadan gözlemler içeren bu aralıklar için yapay olarak çok yüksek olacaktır(çünkü AVG() fonksiyonu için N=örnekler paydası yapay olatak çok düşüktür). Ancak, ilgilenilen periyotlar genellikle performans krizlerini kapsadığından, pratikte bu önemli bir mesele değildir. Belli ki,  ilgilenilen pek çok periyot bolca aktif oturumu kapsamakta, tipik olarakta CPU dan daha fazla aktif oturum kapsamaktadır.

Adım 3 - Çarpıklık bulmak için ortalaması ile bölünmüş varyans eklemek
Adım 2’deki sorguya , ortalama için hem varyans hemde varyans oranı eklenir. Yüksek oran çarpıklığı işaret etmektedir.

select
   to_char(min(sub1.sample_time), 'YYYY-MM-DD HH24:MI:SS') as sample_time,
   round(avg(sub1.on_cpu),1) as cpu_avg,
   round(avg(sub1.waiting),1) as wait_avg,
   round(avg(sub1.active_sessions),1) as act_avg,
   round(variance(sub1.active_sessions),1) as act_var,
   round( (variance(sub1.active_sessions)/avg(sub1.active_sessions)),1) as act_var_mean
from
   (-- altsorgu 1: saniye başı bir satır, SAMPLE_TIME çözümü
     select
        sample_id,
        sample_time,
        sum(decode(session_state, 'ON CPU', 1, 0))  as on_cpu,
        sum(decode(session_state, 'WAITING', 1, 0)) as waiting,
        count(*) as active_sessions
     from
        v$active_session_history
     where
        sample_time > sysdate - (0.25/1440)
     group by
        sample_id,
        sample_time
   ) sub1;


SAMPLE_TIME         CPU_AVG    WAIT_AVG    ACT_AVG   ACT_VAR  ACT_VAR_MEAN
------------------- ---------- -------- ---------- ---------  ------------
2011-11-24 15.47:10     .7         2.8        3.8        5.8         1.4

1 row selected.

Adım 4 – Birden fazla zaman aralıkları için tahmin
Adım 3’teki sorguya  aşağıdaki değişiklikler yapılarak bu yaklaşımı birçok ardışık zaman aralığına genişletiyoruz. Aşağıdaki sorguda birer dakika aralığını seçiyorum.

·         round(sub1.sample_time, 'MI') fonksiyonu ile GROUP BY temeli oluşturulur.
·         Bir sqlplus yer değiştirme değişkeni eklenerekk ilgilenilen genel bir zaman aralığı belirtilir.
·         Varyans kolonu sadece hata ayıklama ile ilgilendiği için kaldırıldı.

select
   to_char(round(sub1.sample_time, 'MI'), 'YYYY-MM-DD HH24:MI') as sample_minute,
   round(avg(sub1.on_cpu),1) as cpu_avg,
   round(avg(sub1.waiting),1) as wait_avg,
   round(avg(sub1.active_sessions),1) as act_avg,
   round( (variance(sub1.active_sessions)/avg(sub1.active_sessions)),1) as act_var_mean
from
   ( -- altsorgu 1: saniye başı bir satır, SAMPLE_TIME çözümü
     select
        sample_id,
        sample_time,
        sum(decode(session_state, 'ON CPU', 1, 0))  as on_cpu,
        sum(decode(session_state, 'WAITING', 1, 0)) as waiting,
        count(*) as active_sessions
     from
        v$active_session_history
     where
        sample_time > sysdate - (&dakika/1440)
     group by
        sample_id,
        sample_time
   ) sub1
group by
   round(sub1.sample_time, 'MI')
order by
   round(sub1.sample_time, 'MI');

old  18:         sample_time > sysdate - (&dakika/1440)
new  18:         sample_time > sysdate - (1/1440)

SAMPLE_MINUTE           CPU_AVG   WAIT_AVG    ACT_AVG ACT_VAR_MEAN
-------------------- ---------- ---------- ---------- ------------
2011-11-24 16.15:00         1.8        3.3        4.9           .5
2011-11-24 16:16:00           1        3.4        4.5           .4
2011-11-24 16:17:00          .6        2.8        3.6           .3
2011-11-24 16:18:00           1        3.7        4.5           .5
2011-11-24 16:19:00          .7        3.2        4.3           .3
2011-11-24 16:20:00          .8        3.5        4.4           .4
2011-11-24 16:21:00           1        2.5        3.5           .4
2011-11-24 16:22:00          .6        1.8        2.3           .3

8 rows selected.

Adım 5 – Daha uzun zaman gemişi için AWR oluşturmak (saatlik)

Adım 4’ deki sorguyu, V$ACTIVE_SESSION_HISTORY tablosundan alınacak veriler yerine daha uzun zaman aralıklarına genişleme yapabilmek için aşağıdaki hale dönüştürüyorum.

·         Yuvarlamayı dakika yerine saate çevirdik.
·         Eski veriyi elde etmek için DBA_HIST_ACTIVE_SESS_HISTORY görünümünü referans aldık.

column sample_hour format a17

select
   to_char(round(sub1.sample_time, 'HH24'), 'YYYY-MM-DD HH24:MI') as sample_hour,
   round(avg(sub1.on_cpu),1) as cpu_avg,
   round(avg(sub1.waiting),1) as wait_avg,
   round(avg(sub1.active_sessions),1) as act_avg,
   round( (variance(sub1.active_sessions)/avg(sub1.active_sessions)),1) as act_var_mean
from
   ( -- altsorgu 1: saniye başı bir satır, SAMPLE_TIME çözümü
     select
        sample_id,
        sample_time,
        sum(decode(session_state, 'ON CPU', 1, 0))  as on_cpu,
        sum(decode(session_state, 'WAITING', 1, 0)) as waiting,
        count(*) as active_sessions
     from
        dba_hist_active_sess_history
     where
        sample_time > sysdate - (&saat/24)
     group by
        sample_id,
        sample_time
   ) sub1
group by
   round(sub1.sample_time, 'HH24')
order by
   round(sub1.sample_time, 'HH24');



Bunun yanında cputime-dbtime-usercalls-gets-awr-daytime.sql.txt sorgusu ile AWR raporundan her saat çekilen snapshotlar kullanılarak birer saatlik dilimlerde CPU kaynak tüketimi, bekleme süresi ve “buffer gets” ile “user calls” işyükü metirlkleri aşağıdaki gibi elde edilebilir.


SNAP_ID BEGIN_HOUR      DB_CPU   DB_TIME  PCNT_CPU  WAIT_   USER_CALLS  BUFFER_
                          _CSPH  _CSPH   _UTILIZE   CSPH   _PH          GETS_PH
------  --------------- -------  -------  --------  ------ ----------   -------
16554  2011-12-22 08:00   1251   375846      0      374595   133809     157182
16555  2011-12-22 09:00   1288   373080      0      371792    98995     175902
16556  2011-12-22 10:01   7847   399668      1      391821    65215     1578118
16557  2011-12-22 11:00   798    370192      0      369394    55754     212906
16558  2011-12-22 12:00   4249   403034      0      398785   247632     504779
16559  2011-12-22 13:00   10796  479532      1      468736   400502     1215195
16560  2011-12-22 14:00   7820   572684      1      564864   420180     542239
16561  2011-12-22 15:00   7555   476859      1      469304   458131     574445
16562  2011-12-22 16:00   6633   472670      0      466037   356792     421098
16563  2011-12-22 17:00   4724   423283      0      418559   282467     310253
16578  2011-12-23 08:00   2267   391711      0      389444   208237     336309
16579  2011-12-23 09:00   2677   404537      0      401860   325800     202084
16580  2011-12-23 10:00   3254   441378      0      438124   202435     278814

Bununda yanında, aşağıdaki sorgu kullanılarak belirli bir toplam işyükü yüzdesi üzerinde “DB CPU” süresine sahip snapshot aralıkları tespit edilebilir. Ortalama zaman ile ilgilenilmeyip, soruna ilk teşhis amacıyla yaklaşılacağı zamanlarda oldukça faydalı bir sorgudur ve AWR raporundan %45 üzerinde beklemeye sebebiyet veren  “DB CPU” ile bekleme olaylarını getirmektedir. Sonuçtanda görüleceği üzere 24 ve 25 Aralık tarihlerinde 22.00 sırasında oldukça yüksek "DB CPU" beklemeleri olmuştur ve bu süreyi analiz edip neyin buna sebebiyet verdiğinin incelenmesi gerekecektir.

select s.begin_interval_time,m.* from
(select ee.instance_number,ee.snap_id,ee.event_name,round(ee.event_time_waited/1000000) event_time_waited,ee.total_waits,
round((ee.event_time_waited*100)/et.total_time_waited,1) pct,round((ee.event_time_waited/ee.total_waits)/1000) avg_wait
from (select ee1.instance_number,ee1.snap_id,ee1.event_name,ee1.time_waited_micro-ee2.time_waited_micro event_time_waited,
 ee1.total_waits - ee2.total_waits total_waits
from dba_hist_system_event ee1 join dba_hist_system_event ee2
  on ee1.snap_id = ee2.snap_id+1 and ee1.instance_number = ee2.instance_number and ee1.event_id = ee2.event_id
  and ee1.wait_class_id <> 2723168908 and ee1.time_waited_micro-ee2.time_waited_micro > 0
 union
 select st1.instance_number,st1.snap_id,st1.stat_name event_name,st1.value - st2.value event_time_waited,1 total_waits
 from dba_hist_sys_time_model st1 join dba_hist_sys_time_model st2 on st1.instance_number = st2.instance_number
 and st1.snap_id = st2.snap_id + 1 and st1.stat_id = st2.stat_id and st1.stat_name='DB CPU'
 and st1.value - st2.value > 0) ee join
(select et1.instance_number,et1.snap_id,et1.value - et2.value total_time_waited
from dba_hist_sys_time_model et1 join dba_hist_sys_time_model et2 on et1.snap_id=et2.snap_id+1
and et1.instance_number = et2.instance_number and et1.stat_id = et2.stat_id and et1.stat_name='DB time'
and et1.value - et2.value > 0 ) et
on ee.instance_number = et.instance_number and ee.snap_id = et.snap_id) m join dba_hist_snapshot s on m.snap_id = s.snap_id
 where  event_name like 'DB CPU' and pct>45
order by m.instance_number,m.snap_id,event_time_waited desc;

BEGIN_INTERVAL_TIME     INSTANCE_NUMBER   SNAP_ID     EVENT_NAME  EVENT_TIME_WAITED TOTAL_WAITS      PCT   AVG_WAIT

23-DECEMBER -2011 06:00:48,005     1     16576 DB CPU      12    1     55,2  12219
23-DECEMBER -2011 18:00:42,468     1     16588 DB CPU      6     1     76,8  5594
24-DECEMBER -2011 02:00:06,020     1     16596 DB CPU      5     1     69,7  4969
24-DECEMBER -2011 09:00:47,738     1     16603 DB CPU      5     1     74,9  5328
24-DECEMBER -2011 13:00:22,603     1     16607 DB CPU      6     1     77,7  6391
24-DECEMBER -2011 17:01:03,253     1     16611 DB CPU      6     1     71,5  6000
24-DECEMBER -2011 21:00:43,758     1     16615 DB CPU      7     1     76,8  7047
24-DECEMBER -2011 22:00:23,115     1     16616 DB CPU      101   1     73,2  100594
25-DECEMBER -2011 06:00:49,762     1     16624 DB CPU      6     1     76,2  6359
25-DECEMBER -2011 10:00:30,452     1     16628 DB CPU      5     1     66,4  5234
25-DECEMBER -2011 14:00:05,864     1     16632 DB CPU      6     1     70,8  6016
25-DECEMBER -2011 17:00:07,622     1     16635 DB CPU      2     1     46,4  2234
25-DECEMBER -2011 18:00:47,090     1     16636 DB CPU      3     1     57,5  2703
25-DECEMBER -2011 22:00:21,855     1     16640 DB CPU      105   1     76,1  104766
26-DECEMBER -2011 02:00:53,972     1     16644 DB CPU      6     1     65,2  6344
26-DECEMBER -2011 06:00:26,805     1     16648 DB CPU      5     1     67,4  5328
26-DECEMBER -2011 10:00:02,420     1     16652 DB CPU      5     1     57,3  5391
26-DECEMBER -2011 18:00:26,902     1     16660 DB CPU      3     1     65,1  3125
26-DECEMBER -2011 19:00:06,399     1     16661 DB CPU      2     1     53,8  2328
27-DECEMBER -2011 03:00:11,050     1     16669 DB CPU      7     1     70,1  6656
27-DECEMBER -2011 07:00:57,589     1     16673 DB CPU      6     1     76,2  5969
27-DECEMBER -2011 19:00:45,861     1     16685 DB CPU      7     1     83    7281
27-DECEMBER -2011 23:00:21,132     1     16689 DB CPU      7     1     54,8  7250
28-DECEMBER -2011 03:00:56,765     1     16693 DB CPU      6     1     63,6  5859
28-DECEMBER -2011 18:00:55,270     1     16708 DB CPU      6     1     66,8  6078
29-DECEMBER -2011 01:00:34,398     1     16715 DB CPU      4     1     49,8  3797
29-DECEMBER -2011 02:00:11,066     1     16716 DB CPU      7     1     68    6500
29-DECEMBER -2011 09:00:53,304     1     16723 DB CPU      5     1     50,2  5297 

Referans:
1)Method-Gapp UKOUG 2011 - Predicting and Profiling of End-User Performance while Focussing on AWR Data
2) A Tour of the AWR Tables, Northern California Oracle Users' Group (NoCOUG) Summer Conference 2008, August 21 2008, Dave Abercrombie
3) Oracle Wait Interface: A Practical Guide to Performance Diagnostics & Tuning, Published 2004 McGraw-Hill Professional, 2004, Richmond Shee, Kirtikumar Deshpande, K. Gopalakrishnan
4) Average Session Load (ASL)The Golden Metric? , Kyle Hailey

0 yorum:

Yorum Gönder