5 Şubat 2011 Cumartesi

Otomatik Bellek Yönetimi - Automatic (Shared) Memory Management

Oracle Veritabanı 11g Otomatik Bellek Yönetimi ve Dinamik Performans Parametreleri


Bugün anlatacaklarım ile; SGA (System Global Area) belleği içerisinde yer alan bileşenleri, veritabanını otomatik bellek yönetimine geçirmeyi (automatic memory management), SGA bileşenlerini elle belirleme, otomatik PGA (Program Global Area) tanımlamasını yapma gibi konular hakkında bilgi sahibi olacaksınız.


Bellek Yönetimi (Memory Management)


Yalnızca Oracle veritabanı için değil, veritabanının bulunduğu sistemin de sınırlı belleği ve performansı bulunmaktadır. Oracle veritabanı yöneticisi olarak bize verilmiş olan donanım ile en iyi performansı sunmak belki de en büyük amacımız gibi görülmektedir. ADDM (Automatic Diagnostic Database Monitor) bulgularını inceliyorsunuz ve size sürekli, buffer cache'in düşük olduğunu, bunun nedeni olarak ise hard parse'ların arttığını göstermektedir. Her zaman ve her durumda "RAM eklerler ve SGA'yı arttırırım" cevabı geçerli olmaz, olması da mümkün değil zaten. SGA veya PGA ile oynamadan önce, yeni bir RAM takmadan önce bakabileceğiniz aslında o kadar çok yer var ki. Bir de tabii sistemden Oracle veritabanına, çok fazla veya çok az kaynağın aktarıldığı durumlarda da bir takım sorunlar meydana gelebilir. Örneğin sistemden aşırı kaynak isterseniz (neredeyse işletim sisteminin sahip olduğu RAM kadar) bu durumda işletim sistemi kernel'ı çalışamaz hale gelecek ve swap kullanımları gündem dahilinde olacaktır. Yok hayır, benim tutturmam gereken belirli hedefler var ve bu hedefler dahilinde de RAM'in sadece %50'sini Oracle'a aktarabilirim derseniz ne olabilir? Cevap, hiçbir şey olmayabilir. Oracle'a tahmininizden daha az RAM ayırsanız bile belki entegre ettiğiniz uygulama daha fazlasına ihtiyaç duymayacak? Peki tam bu noktada, otomatik bellek yönetimini Oracle neden tavsiye etmekte?

Günümüzde birçok veritabanı teknolojik gelişmeler, artan rekabet, azalan entegrasyon satış fiyatlarına karşın azalmayan ve aksine artan maliyetler, firmaları bir takım önlemler almaya itti. Bunların başında da kaynakların çok daha etkili, verimli ve yeterli kullanılması gelmekte. Bu bağlamda Oracle veritabanına, 10g versiyonu ile birlikte Otomatik Paylaşılan Bellek Yönetimi (Automatic Shared Memory Management), 11g versiyonu ile birlikte de Otomatik Bellek Yönetimi (Automatic Memory Management) özelliğini eklediler. Bu yapıların en büyük avantajı 9i versiyonunda elle yönetilen SGA ve PGA dinamik bileşenlerinin artık Oracle tarafından yönetilmesini sağlamak ve veritabanı yöneticisinin işlerini hafifletmek. Unutmamamız gereken bir şey var ki insanoğlunun ürettiği uçakları bile hala insanlar indirmekte, kaldırmakta ve aksi bir durumda yine insan müdahalesine ihtiyaç duyulmakta. Ben bu konuyu hep böyle özetlemişimdir ve bu noktada Oracle'ın da tavsiyesi olan bu otomatik bellek yönetimine aslında çok da fazla güvenmemek gerekebilir. Bunu ben söylemiyorum, Oracle söylüyor ama zaten her zaman, konudan emin olsak bile "neden" sorusunu sormalıyız ki kendimizi daha da geliştirelim.

Bugün biraz felsefi günümdeyim sanırım ve artık bu laf kalabalığını bırakıp, konunun teknik detaylarını incelmeye başlayalım.

Oracle Veritabanı Bellek Yapısı

Bir Oracle veritabanında 2 adet bellek yapısı bulunmaktadır ve yönetilmektedir. Bu bellek yapılarının kendi içerilerinde bileşenleri bulunmaktadır. Bileşenlerin herbirinin farklı amacı vardır ve farklı amaçlara hizmet etmektedir.

System Global Area (SGA): Bir Oracle instance'ının veri ve kontrol bilgisini içeren bellek yapısıdır. SGA, bütün sunucu ve arka plan görevleri tarafından paylaşılmaktadır. SGA içerisinde tutulan bilgiler arasında cache'lenmiş veri blokları ve paylaşılan SQL alanı gibi bilgiler bulunmaktadır.
Program Global Area (PGA): Sunucu ve arka plan görevlerinin veri ve kontrol bilgisini saklamaktadır. PGA alanı paylaşılmakta olan bir alan değildir ve bir sunucu veya arka plan görevi çalıştığı zaman kullanılmaktadır. 

SGA Dinamik Bileşenleri

SGA'nın bünyesinde aşağıdaki bellek yapıları bulunmaktadır;

Buffer Cache: Veritabanından gelen veri bloklarının cache'lendiği alandır. Cache içerisinde blokların tutulmasının amacı ise sürekli fiziksel okuma yapmak yerine, sık kullanılan sorgulardan gelecek blokların burada barındırılarak çok daha hızlı çıktılar üretmeye yarar. DB_CACHE_SIZE Oracle parametresini ayarlayarak bu bileşen için bir alan tanımlaması yapabilirsiniz. Buffer cache veritabanı içinde paylaşılan bir alandır. Sunucu görevi datafile'lardan okuma yaparak buffer cache içerisine yazmaktadır. Performansı arttırmak için bazı durumlarda sunucu görevi, tek bir okuma operasyonu sırasında birden çok blok okuyabilmektedir. DBWn görevi ise buffer cache'de saklanan verileri, datafile'lara yazan görevdir. Performansı arttırmak için bazı durumlarda DBWn görevi, tek bir yazma operasyonu sırasında birden çok blok yazabilmektedir. Buffer cache içerisinde tutulacak veya silinecek blokların kararını LRU (Least Recently Used) isminde bir algoritma karar vermektedir. Yukarıdan aşağıya doğru inen bir liste düşünün. Sunucu görevinin buffer cache içerisinde ilettiği blok, bu listenin tam ortasından girmektedir. Kullanım durumuna göre yukarı veya aşağı doğru gidip gelebilir. En tepeye çıktığı zaman tabii ki gidebileceği başka bir yer yoktur fakat en dibe indikçe buffer cache'den çıkarılma durumu bulunmaktadır. Bu tamamen bloğun ne kadar meşhur olduğuna bağlıdır dersem aslında çok ufak bir hata payı ile yanılmış olurum. Biraz sonra anlatacağım yapı ile bu listenin içerisine girecek blokların aşağıdan mı yoksa yukarıdan mı giriş yapacağını belirleme şansınız bulunmakta.

Buffer cache içerisindeki buffer'ları 4 aşaması bulunmaktadır. 

1) Pinned: Bu aşamada olan bir buffer'a ya yazma işlemi yapılmaktadır ya da okuma işlemi. Diğer işlemlerin bu bloğa erişim sağlayabilmesi ve okuma yapabilmesi için beklemeleri gerekmektedir.
2) Clean: Bu buffer artık pinned değildir ve yaşlanmaya yüz tutmuştur. Bunun anlamı ilgili buffer disk ile senkronize olmuş olabilir veya bu bir başka bloğun snapshot'ıdır.
3) Free/Unused: Buffer temizdir çünkü instance yeni başlatılmıştır. Clean aşamasına çok benzemektedir ancak aradaki fark bu buffer'lar üzerinde henüz bir işlem yapılmamıştır, yani işlenmemiştir. 
4) Dirty: Pinned durumda değildir ancak veri bloğu üzerinde yapılmış değişikliğe sahip buffer'ın DBWn tarafından veritabanına yazılması gerekmektedir. Bu yazma işleminden sonra Clean aşamasına geri dönecektir.

Bir Oracle veritabanı birden çok blok boyutlarını desteklemektedir. Bu boyutlar 2 KB ile 32 KB arasındadır. Bu değer Oracle için varsayılan olarak 8 KB olarak atanmaktadır. Bu varsayılan blok boyutu SYSTEM tablespace'i için geçerlidir ve DB_BLOCK_SIZE parametresi ile belirlenmektedir. DBCA (Database Configuration Assistant) kullanırken eğer General Purpose şablonunu seçerseniz 8 KB DB_BLOCK_SIZE geleceğini ve değiştiremeyeceğinizi göreceksiniz. Değiştirmek isterseniz "Custom Template" seçeneği ile devam etmeniz gerekmektedir. Standart olmayan blok boyutlarını tanımlamak için kullanılacak diğer parametreler ise;

* DB_2K_CACHE_SIZE
* DB_4K_CACHE_SIZE
* DB_8K_CACHE_SIZE
* DB_16K_CACHE_SIZE
* DB_32K_CACHE_SIZE

Yukarıdaki parametrelerin hiçbirini DB_BLOCK_SIZE'ı değiştirmek için kullanamazsınız ve veritabanı yaratıldıktan sonra DB_BLOCK_SIZE'ı değiştiremezsiniz. Bu parametreler yalnızca blok buffer'ları için tanımlanan bellek alanlarıdır. Oracle otomatik olarak yukarıdaki nK bellek alanlarını yönetmez. Bu parametreleri eğer kullanmak istiyorsak bizim tanımlamamız gerekmektedir. Otomatik bellek yönetiminde de bu parametrelere SGA veya PGA'dan bellek aktarılmamaktadır. Eğer DB_BLOCK_SIZE parametresi nK değerine eşit ise DB_nK_CACHE_SIZE parametresini ayarlayamazsınız. 

Her buffer cache'in limitli bir alanı bulunmaktadır. Bu durumda veritabanındaki bütün bilgileri buffer cache içerisinde tutmak gibi bir şansınız yoktur. Buffer cache tamamen dolduğu zaman hala güncelleme yapılıyorsa buffer cache içerisindeki dirty buffer'ların, disk'lere yazılarak yeni yer açılması sağlanır. Bu duruma "cache miss" denmektedir. "Cache hit" ise veri isteklerinde sonucun buffer cache'de olması ile artan bir değerdir. Sonuç olarak cache hit > cache miss olması daha iyidir.

Bir veritabanı yöneticisi birden çok buffer havuzu (buffer pool) yaratarak performansı arttırabilir. 3 çeşit buffer havuzu bulunmaktadır.

1) KEEP: Sık olarak kullanılacağı düşünülen blokların buffer cache'de normalden daha uzun kalmasını sağlamak istiyorsanız objeyi buffer pool keep'e atabilirsiniz. Not, bunu yapmanız ilgili buffer'ların buffer cache'de sonsuza kadar kalacağını garanti etmez. Yalnızca LRU listesine tepeden girer ve kullanılmadıkça buffer cache'den yine de çıkar. Bu sayede I/O operasyonlarını azaltabilirsiniz. Keep havuzunu aktif hale getirmek istiyorsanız DB_KEEP_CACHE_SIZE parametresini tanımlamanız gerekmektedir. Bu parametre otomatik bellek yönetimi tarafından ayarlanmamaktadır.
2) RECYCLE: Bu blokların buffer içerisinde çok az kullanılacağını söylemek isterseniz DB_RECYCLE_CACHE_SIZE parametresine belirli bir değer atamanız ve ilgili objeyi tanımlamanız gerekmektedir. 
3) DEFAULT: Bu havuz her zaman var olacaktır. İlgili parametre DB_CACHE_SIZE'dır. Buffer cache'in kendisidir diyebiliriz.

Bu arada ufak bir hatırlatma; Keep veya Recycle havuzu, default buffer cache'in alt kümesi değildir. Bu ikilinin kullanım şekli ise;

SQL> CREATE INDEX IDX_OGAN_DENEME
2 STORAGE (BUFFER_POOL KEEP);

SQL> ALTER TABLE OGAN_DENEME
2 STORAGE (BUFFER_POOL RECYCLE);

Keep ve Recycle tanımlamalarını yukarıdaki gibi yapabilirsiniz. STORAGE kullanımını ise CREATE ve ALTER komutları ile birlikte, tablo, index, veya cluster yaratırken kullanabilirsiniz. DEFAULT eğer STORAGE belirtmezseniz ilgili obje için kullanılacak buffer havuz tipi olacaktır. Bir objenin yaratılması sırasında DEFAULT buffer havuzu kullanılmış ise ve sonradan da KEEP veya RECYCLE'a alınmış ise buffer cache'de bulunan buffer'lara bir değişiklik gönderilmez. İlgili buffer'lar temizlenene kadar önceki yerinde kalmaya devam ederler. Burada kadar söylediklerimden şunu çıkarabiliriz; buffer pool'lar "segment"lere atanır. Zaten indeks, tablo ve cluster'lar birer segment'tir. Dolayısıyla bir tablespace içerisinde bulunan birden fazla segment, farklı buffer havuzlarında tutulabilmektedir. 

Shared Pool: Shared pool veya paylaşılan havuz bir SGA dinamik bileşenidir. SHARED_POOL_SIZE parametresinin değeri ayarlanarak boyutu değiştirilebilir. Bu alan birden çok bağlantının paylaşılan bilgilerini içerir mesela SQL çalıştırma planları gibi. Shared pool AMM veya ASMM ile otomatik olarak yönetilebilmektedir.

1) Library Cache: Library cache, SQL ve PL/SQL alanlarını, planlarını barındırmaktadır. PL/SQL alanları olarak procedure ve function'lar, package'lar ve trigger'lar bulunmaktadır. 
2) Data Dictionary Cache: Bu alan data dictionary'e ait olan objelerin bellekte tutulmasını sağlar.
3) Result Cache: Bu alanın amacı SQL sorgusunun sonuçlarının ve PL/SQL fonksiyon sonuçlarının cache'lenmesini sağlamaktadır. Bunun amacı ilerideki çalıştırmaların daha hızlı olmasını sağlamaktır.
4) User Global Area: UGA Oracle'ın shared sunucusu için gerekli bağlantı bilgilerini tutmaktadır. Large Pool'un ayarlanmadığı durumlarda bu bilgiye sahip olmaktadır.

Large Pool: Bir veritabanı yöneticisi yine opsiyonel olarak large pool alanını ayarlayabilir. Large pool içerisinde; shared sunucular için bağlantı bilgileri, I/O sunucu görevleri, RMAN için I/O slave buffer'ları, paralel çalıştırmalarda kullanılacak buffer'lar ve advanced queuing bellek tablo alanları tutulmaktadır. Large pool AMM veya ASMM ile otomatik olarak yönetilebilmektedir. Bunun dışında LARGE_POOL_SIZE girilerek de istenilen boyutlandırma sağlanabilir. Bu alan eğer otomatik bellek yönetimi devrede ise genelde yedeklemenin çok koldan ilerlediği ve paralel olarak çalıştığı durumlarda yeniden boyutlandırılır ve boyutu arttırılır. Daha sonra başka bir bileşenin ihtiyacı olursa AMM veya ASMM daha önce verdiği ek alanı geri alabilir.

Java & Streams Pool: JVM içerisinde bulunan veriler ve java kodları için kullanılan bellek parçasıdır. STATISTICS_LEVEL parametresi TYPICAL olarak ayarlandığı zaman "java pool advisor" otomatik olarak çalışmakta ve bu alan için bize kullanımı ile ilgili bilgiler aktarmaktadır. 
Streams Pool ise Oracle'ın veri replikasyonunu sağlayan Streams'i için kullanılan bellek alanıdır. Burada , Streams için gerekli kuyruk(sıra) bilgileri barındırılmaktadır. Bu bellek alanı da yine AMM veya ASMM aktif iken otomatik olarak yönetilmektedir ve varsayılan değeri sıfırdır. Oracle Streams kullanıldıkça bu havuzun değeri granule boyutu kadar arttırılacaktır. 

Redo Log Buffer: AMM veya ASMM tarafından otomatik olarak yönetilemeyen, SPFILE'ın geçerli olduğu bir instance için yalnızca spfile'a değişikliği yazılabilen, bir Oracle sunucu görevinin, her DML veya DDL ifadesinden sonra redo girişlerini kopyaladığı alandır. Bu alan dönüşümün olduğu ve içerisindeki veri girişlerinin sürekli ve çok hızlı bir şekilde değiştiği bir alandır. Buradaki veriler, ilgili transaction commit ettikten sonra LGWR tarafından online redolog dosyalarına yazılırlar. Peki LGWR'nin yazmasına neler neden olabilmektedir?

a) Redolog buffer'ın 1/3'ü dolduğu zaman.
b) Her 3 saniyede bir.
c) Herhangi bir kullanıcı commit işlemi gönderdiği zaman
ç) DBWn dirty buffer'ları buffer cache'den fiziksel veri dosyalarına yazmadan hemen önce. 
d) Redolog buffer 1MB olduğu zaman.

Otomatik Bellek Yönetimi (Automatic Memory Management)

Otomatik bellek yönetimi ile Oracle, SGA ve PGA'yı gelen talepler doğrultusunda dengede tutup, yükün geldiği noktadaki bellek bileşenine ağırlık verilmesini sağlar ve Oracle tarafından eğer özel bir talebiniz yoksa kullanılması tavsiye edilen bir yönetim sistemidir. Bu özelliği aktif hale getirebilmeniz için ayarlamanız gereken 2 tane parametre bulunmaktadır. Bunlar MEMORY_TARGET ve MEMORY_MAX_TARGET'tır. Ayarlandıkları zaman Oracle, MEMORY_TARGET boyutu kadar alanı SGA ve PGA üzerinden otomatik olarak yönetir ve yük dengesini sağlar. AMM özelliğini Enterprise Manager kullanarak da aktif hale getirebilirsiniz. 

MEMORY_TARGET dinamik bir parametredir ve SPFILE kullanan bir instance için dinamik olarak değiştirilebilir. MEMORY_MAX_SIZE ise MEMORY_TARGET'ı sınırlayan bir huduttur. Şu anda AMM Linux, Solaris, HPUX, AIX ve Windows için kullanılabilmektedir ve işletim sistemi ile sürekli bir alışveriş içerisindedir. Bu sebepten dolayı diğer platformlarda henüz geliştirilmesi yapılmamıştır ve kullanılamaz. 

MEMORY_TARGET belirlemenize ve AMM'yi devreye almanıza rağmen SGA dinamik bileşenlerinin boyutunu yine de ayarlayabilirsiniz. AMM aktif iken ilgili bileşene vereceğiniz değer ile şunu demek istersiniz; örneğin SHARED_POOL_SIZE'a 100MB değer verdiğinizi düşünelim. AMM aktif, bu durumda SHARED_POOL_SIZE ne olursa olsun 100MB'ın altına düşemez demek istersiniz.

* Eğer SGA_TARGET ve PGA_AGGREGATE_TARGET değerleri sıfırdan hariç bir değere ayarlanmış ise bu değerler sırası ile SGA ve PGA'nın asgari değerleri olarak tanınacaktır. MEMORY_TARGET değeri SGA + PGA'ya eşit olabilir dolayısıyla MEMORY_MAX_TARGET'a da.
* Eğer SGA_TARGET sıfırdan farklı bir değere atanmışsa veritabanı yalnızca SGA'nın dinamik bileşenlerini tune edecektir. PGA bu durumda bağımsız olarak tune edilecektir. 
* Kullanıcının elle tanımladığı SGA bileşenleri, AMM tarafından otomatik olarak tune edilmezler. 

Bellek hedefleri ile ilgili olarak Enterprise Manager'ı veya V$MEMORY_TARGET_ADVISOR dinamik performans görüntüsünü kullanabilirsiniz. MEMORY_TARGET'ın sıfırdan farklı ancak SGA_TARGET ve PGA_AGGREGATE_TARGET dahil olmak üzere diğer bütün bileşenlerin değeri sıfır olduğu zaman SGA + PGA Oracle tarafından yönetilmektedir. MEMORY_TARGET parametresini sıfır olacak şekilde ayarlarsak Oracle SGA_TARGET ve PGA_AGGREGATE_TARGET değerlerini güncelleyecek ve MEMORY_TARGET'ın elinde olan kadarını dağıtacaktır. Bu aşamadan sonra SGA_TARGET ve PGA_AGGREGATE_TARGET değerlerini de sıfır olacak şekilde ayarlarsak, SGA dinamik bileşenlerine gerekli değerler atacaktır.

Otomatik Bellek Yönetiminin Gözlenmesi

V$MEMORY_DYNAMIC_COMPONENTS dinamik olarak ayarlanmış bellek bileşenlerini göstermektedir ve buna SGA + PGA da dahildir. V$MEMORY_TARGET_ADVICE dinamik performans görüntüsü ise MEMORY_TARGET için tune edilebilecek bilgileri içermektedir. V$MEMORY_TARGET_ADVICE görüntüsünü sorgularken, MEMORY_SIZE_FACTOR sütunu bize 1 olduğu yerde o anki bellek boyutunu vermektedir. Bunun dışında kalan satırlar için bu boyut faktörüne göre size farklı tahminler sunulmaktadır. Bu tip tavsiyeleri dikkate almak veya almamak tabii ki size kalmıştır ancak genelde kontrol edilmesinde fayda vardır. Her veritabanının bir anı diğer bir anı ile asla aynı değildir. Bir yükün nereden geleceğini, hangi parametrenin ne zaman değiştirilmesi gerektiğini çoğu zaman bilemeyebilirsiniz veya bu kadar sıkı takip etmeyebilirsiniz. Bu sebepten dolayı ya Enterprise Manager'dan ya da bu görüntüleri sorgulayarak gerekli bilgilere erişebilirsiniz.

Efektif Bellek Kullanımı

En efektif ancak en imkansız bellek kullanımı, bütün SGA'nın fiziksel belleğe yerleştirilmesi ile olabilirdi. Yani ilk başta bahsettiğim konu. Bütün işletim sistemi RAM'inin Oracle'ın SGA'sı için ayrılması durumu. İşletim sistemi hiç mi kaynak tüketmiyor? Merak etmeyin, bunun da bir çözümü mevcut. LOCK_SGA isminde bir parametre var ve bu parametrenin varsayılan değeri FALSE'dur. TRUE olarak ayarlandığı zaman SGA'nın fiziksel bellek içerisinde kilitlenmesini sağlayabilirsiniz. AMM ve ASMM ile birlikte kullanılamayan bu parametreyi ömrünüzde hiç TRUE olarak ayarlamadıysanız bırakın FALSE kalsın. Ciddi yük ile sarsılan veritabanlarında daha fazla fiziksel bellek ihtiyacı doğacağı için Oracle'ı bir canavara çevirebilir ve sistemi tamamen swap alanına mahkum edebilirsiniz. Swap alanı kullanmakta olan bir sistem = kabul alınamayan bir proje (çok abarttım sanırım) .

Bir SQL sorgusu koştuğunuz ve veritabanından veri istediğiniz zaman aslında bir veya birden fazla blok istemiş olursunuz. Hatırlarsanız CBO da blok üzerinden işlem yapıyordu. Eğer istediğiniz block veritabanında SGA içerisindeki buffer cache içerisinde yer alıyorsa bu bir mantıksal okuma olarak karşınıza gelir. Yer almıyor ise fiziksel veri dosyaları okunur ve fiziksel I/O yapılır. Her seferinde buffer cache içerisinde bulunan bloklara "buffer cache hit ratio" denmektedir. Bu değerin yüksek olması daha iyidir çünkü fiziksel I/O azalıyor demektir. Bir buffer cache hit oranının %99'un üzerine çıktığını görmeniz pek normal bir durum olmasa da bu durum sisteminizin çok iyi tune edildiği anlamına gelmemektedir. Her çeşit hit ratio'larından %99 ve üzeri puan toplasanız bile bir arkadaş yine gelip sonsuz bir döngü içerisinde insert işlemi yapabilir ve her insert'ten sonra da commit edebilir. Nasıl bir işkence olurdu değil mi? E ama sizin bütün hit ratio'larınız %99 idi? Bir de FTS (Full Table Scan) işlemlerine dikkat etmeniz gerekmektedir. Eğer yapılan işin öneminden dolayı ya da uygulamanın işleyişinden dolayı FTS operasyonları normal karşılanıyorsa bütün bu operasyonun buffer cache'den gelmesi gibi bir durum söz konusu olmayabilir. Bu durumda çok iyi tune edilmiş bir uygulamanın buffer cache hit oranı düşük de olabilir. Uzun sözün kısası, hit ratio'lara çok fazla takılmayın, önemli olan veritabanı üzerindeki uygulamanızın neler yaptığı ve ne kadar performanslı çalıştığı. Sizin uygulama üzerinde yapacağınız iyileştirmelerle zaten bu hit oranı yukarı doğru bir eğilim gösterecektir. Teknik olarak, günün sonunda bütün blokların buffer cache'de olmasını istiyoruz zaten.

Efektif bellek kullanımı için girilebilecek bir başka konu ise "Library Cache"in tune edilmesidir. Library cache Share pool'un bir parçasıdır ve içerisinde meşhur SQL "explain plan"ları barındırır. Aynı zamanda kilitleri ve kontrol yapılarını da içerir. Bir dipnot, tablo bazında yapılan kilit işlemlerine "lock", library cache üzerindeki bir kaynağın tahsisinden dolayı alınan kilitlere ise "latch" denmektedir. "Library Cache Lock" bekleme olayları ile karşılaşırsanız eğer bu demek oluyor ki library cache'de paylaşılan bir plan üzerinde kullanım varken, diğer bir kullanıcının buna erişmesi ve "latch" almak istemesinden dolayı oluyor diyebiliriz. Konumuza dönersek, bu explain plan'lar yani bir sorgunun hangi yoldan gideceğini gösteren haritalar, sürekli paylaşılmaktadır. Tabii burada dikkat edilmesi gereken durum bu haritaların gelen yüzlerce bağlantı tarafından parçalanması değil, library cache'in yükünün ayarlanmasıdır. Küçük bir library cache'e sahipseniz daha az paylaşırsınız ve sorgular buradan daha az faydalanırlar. CBO dynamic sampling yapmak zorunda kalır ve kendi yolunu kendi çizer. Her dynamic sampling operasyonu bir hard parse'dır ve can sıkıcı olabilir. Bu sebepten dolayı sürekli kullanılan sorgular için genelde "bind variable" kullanın ve bütün sorguyu aynı bırakarak, CBO'nun bu planı görmesini ve ek bir parse maliyeti olmamasını sağlayabilirsiniz. Bu konu ile ilgili çok detaya girmek istemiyorum çünkü başlı başına konuşabileceğim bir konudur. Sorgularınızı yazarken ve çalıştırırken dikkat etmeniz gereken konu "çalıştır" dediğiniz sorgunun genel yapı olarak sürekli değişmiyor olması. Yaptığınız her en ufak değişiklik, Oracle tarafından farklı bir sorgu olarak algılanır ve eğer bir de içeride bind variable yerine literal (numara veya karakter) kullanıyorsanız bu durumu daha da vahim hale getirir. Bir de üzerine cursor_sharing parametreniz SIMILAR'da kalmış ise vay halinize.

CURSOR_SHARING parametresini birçoğunuz biliyorsunuz ya da en azından duymuşluğunuz vardır. Ben aslında bu parametrenin ne olduğunu ya da 11g ile gelen ve aklınızda soru işaretleri bırakan ADAPTIVE özelliğini açıklamayacağım çünkü konumuz tam olarak bu değil. CURSOR_SHARING parametresi literal kullanımını görüp bunun birer bind variable olarak explain plan'larının saklanmasını sağlayan parametredir. Hayatınız boyunca göreceğiniz birçok veritabanında bu parametrenin FORCE olarak tanımladığını göreceksiniz. Benim bulunduğum ve yönettiğim veritabanlarında ise bu parametreyi hiçbir zaman FORCE olarak göremezsiniz. Nedenlerini de yazmak istersem yine başka bir konuya geçmiş olurum çünkü bununla ilgili uzun bir yazı yazabilir ya da konuşabilirim.

Steven Feuerstein'ın bir sözü vardı "SQL is bad, use PL/SQL". Bu ifadesinin arkasında keşke sadece 1 neden olsa da ben size sadece onu anlatsam burada ancak ne yazık ki tek bir sebep yok. Burada söyleyeceğim sebep, eğer birden çok SQL çalıştırıyorsanız uygulamanızda, bu sorguların tamamını bir PL/SQL bloğu içine gömün ve burada çalıştırın. Bu bir procedure olabilir. Ardından bu procedure'ü çağırın. Bu, SQL ifadelerinin mecburi olarak paylaşılmasını sağlayacak çünkü hepsi aslında bir tek lokasyonda bulunuyor olacak. Bunun dışında içerideki SQL'ler çoktan parse edilmiş olacak çünkü stored procedure yaratılırken parse edilmiş olacaklar!

DBMS_SHARED_POOL paketini de objeleri library cache içerisinde takip etmek için kullanabilirsiniz. Bu durumda sizin yeni bir şans doğmaktadır. Objelerin yeniden yüklenmesini ve yeniden derlenmesini (recompile) engellemiş olabilirsiniz. Burada da Thomas Kyte'dan bir alıntı "a good parse is no parse". Kendisi hard parse olayını aşmış, soft parse da yaptırmadan sorgu planları çıkartmanın çalışmalarını yaptığı için burada bu konulara yer veremiyorum ne yazık ki :) Bir sonraki derste inşallah.

Otomatik Paylaşılan Bellek Yönetimi (Automatic Shared Memory Management)

Umarım bu noktaya kadar yazdıklarım faydalı olmuştur. Sıradaki konu ise ASMM olarak ifade ettiğim yapı. 10g ile birlikte aramıza katılan ASMM'de amaç SGA'nın dinamik bileşenlerini otomatik olarak yönetmektir. 11g AMM'den farkı PGA'nın yönetimi dahil değildir. 11g'de tercih edilebilir mi? neden olmasın. Sabit bir PGA kullanmak istiyorsanız ancak SGA'nın dinamik olmasını amaçlıyorsanız ASMM sizin için uygun demektir. AMM için bahsettiklerimin tamamı aslında ASMM için de geçerli diyebiliriz. ASMM'de yalnızca SGA'nın dinamik bileşenleri otomatik olarak tune edilir ve o anki veritabanı yük dağılımına göre SGA bileşenleri üzerinde granül geçişleri sağlanır.

ASMM SGA'nın yönetimi için MMON (Manageability Monitor) ve MMAN'dan (Memory Manager) tüyolar alır. MMON'u nerede görmüştük? Metric değerlerinin eşiği aştığı durumlarda gerekli kontrolleri yapan ve AWR ile ilgilenen arkadaşımızdı. MMON'un aldığı kararları da uygulayan arkadaşımız MMAN'dır. MMON'u bir köle, MMAN'ı ise usta olarak görebilirsiniz ve tabii ki asıl işi yapan MMON'dur. SGA bellek broker'ı her birkaç dakikada bir gerekli kontrolleri yapar ve veritabanının yük dağılımını inceler. MMON ve MMAN'ı kullanarak da hangi dinamik bileşenin, hangi değere çıkartılması veya azaltılması kararını alır. Bütün bunların ardından ASMM'nin neleri aktif olarak kullandığını söylemek istiyorum;

a) Arka plandaki görevleri kullanarak istatistikleri toplar.
b) Bellek Danışmanlarını (Memory Advisor) kullanır.
c) "What-if" isimli bir algoritma kullanarak, ataması gereken değeri algılar.
ç) Belleği ayrılması gerektiği gibi ayırır.
d) SPFILE'a yazılmış olan ancak değişikliği henüz yapılmamış bütün değerleri korur.

ASMM'yi aktif hale getirmek için önce bir değer bulmamız gerekmektedir ve bu değeri SGA_TARGET'a vereceğiz.

SQL> SELECT ((SELECT SUM(VALUE) FROM V$SGA) - (SELECT CURRENT_SIZE 
2 FROM V$SGA_DYNAMIC_FREE_MEMORY)) SGA_TARGET FROM DUAL;

SQL> ALTER SYSTEM SET SGA_TARGET = SCOPE = SPFILE|MEMORY|BOTH;

AMM'den ASMM'ye geçmek için daha önce de bahsettiğim gibi MEMORY_TARGET parametresini sıfıra getirmek gerekmektedir. SGA_TARGET'ın sıfır olarak ayarlanması ASMM'yi devre dışı bırakır. Devre dışı kalan ASMM'nin yönettiği toplam SGA alanı, SGA'nın dinamik bileşenleri üzerinde dağıtılır. 

PGA (PROGRAM GLOBAL AREA)

"Shared Server" kullanımının olduğu durumlarda PGA'nın bir parçası SGA içerisinde yer alabilmektedir ancak PGA normalde paylaşılmayan bir alandır ve bir sunucu görevinin veri ve kontrol bilgilerini içerir. 

PGA belleğinin parçaları ise;

Private SQL Area: Bu alan bind bilgisini ve run-time bellek yapılarını içermektedir. Bu bellek her bağlantı (session) için ayrı bir değer tutar ve kullanıcının koştuğu SQL sorgusuna bağlıdır. Örneğin bind variable'lar, cursor değerleri vb. Bütün kullanıcıların koştuğu aynı SQL sorgusu için her kullanıcının kendine ait bir özel SQL alanı oluşur ve eğer sorguda bir bind variable kullanılmış ise içerik burada saklanır. Eğer bir bağlantı shared server üzerinden bağlanmış ise bu alanın bir parçası SGA içerisinde saklanır.

Cursor & SQL Area:  Bir Oracle Call Interface (OCI) programı dolaylı olarak cursor açabilir ve açtığı zaman da burada saklanır. Bu cursor'lar yeniden erişilmek istendiği zaman bu bellekten okunurlar.

Work Area: Kompleks sorgular için de bir çare düşünülmüş ve bu bellek alanı yaratılmış. PGA'nın çok büyük bir bölümü burası için ayrılmaktadır. Peki kompleks sorgudan kasıt nedir?

a) ORDER BY, GROUP BY, ROLLUP gibi ifadeler içeren sorgular.
b) Hash-Join
c) Bitmap Merge
ç) Bitmap Create
d) Bulk yükleme operasyonları için kullanılan yazma buffer'ları.

Bu alan kontrol ve tune edilebilen bir alandır. Genel olarak daha büyük çalışma alanları performansı arttırabilir.

Session Memory: Bağlantı ile ilgili bütün bağlantı bilgilerinin (login information) tutulduğu bellek alanıdır. 

PGA'nın yönetimi PGA_AGGREGATE_TARGET ile otomatik olarak yapılabilmektedir. PGA'nın bu değeri geçmemesi garanti altına alınmaya çalışılır.

İyi çalışmalar dilerim.

Ogan

1 yorum:

Ali Yavuz dedi ki...

Tesekkurler

Takip et: @oganozdogan