Veriye Etkin Erişim Yöntemleri – 1

Veriye Etkin Erişim Yöntemleri – 1

Herkese Selam,

Bu yazıda sizlerle veriye erişirken uygulayacağımız yöntemlerin performanslarını, etkilerini, farklarını ve veriye erişim performansımızı nasıl geliştirebileceğimizi anlatacağım. Umarım farkındalık anlamında faydalı bir yazı olur.

Günlük iş yaşantımızda biz developerlar veya DBA’ler bir çok kez veriye erişirken performans sorunları ile karşı karşıya çalışıyoruz. Çoğu kez unit testlerimizi fazla uzun sürmesin diye daha küçük veri setleri üzerinde yapıp fonksyonelliği ölçüyoruz ancak stres testi yapıp saniyelik throughput’u pekte önemsemiyoruz bunun sonucunda işi devreye aldığımızda acı gerçekle karşı karşıya kalabiliyoruz. Özellikle büyük veritabanları üstünde geliştirme yapan developerlar bu durumu daha sık yaşıyorlar ve sorun canlı sistem üzerinde meydana geldiğinde zaman organizasyonel baskılarla sıkışmaya başlıyorlar. Veriye ne kadar etkin erişirsek yada etkin eriştiğimizi düşünsek bile DB üstünde çalışan uygulamalarımızda stres testi mutlaka yapıp sonucu ölçümlemeden canlı ortama çıkmamalıyız. Bu noktadan hareketle stres testi yapma seviyesine gelmeden DB üstünde çalışacak kodlarımızın veriye erişim yöntemini nasıl etkin kılarızı konuşmak farkındalık anlamında gerek developer’lara gerekse DBA’lere katkı sağlayacağını düşünüyorum.

(NOT:Bu noktadan sonra anlatacağım teknik içerik Oracle Veritabanında deneyimlediğim ve Oracle kaynaklarından araştırdığım mevzular, DB2 veya MSSQL gibi ürünlerin veri erişim yöntem davranışlarını incelemediğimden bu yazıyı “her veritabanı yönetim sistemi için doğrudur” önermesini kabul ederek değerlendirmek yanlış olacaktır.)

Peki Veriye Etkin Bir Şekilde Nasıl Erişiriz ?

Aslında etkin veri erişim tekniğinin nasıl bulunması gerektiğini anlatmadan önce aşağıdaki 3 başlık üzerinde biraz durup değerlendirmek lazım.

1-) Kaynak Tüketimi (Resource Consumption): Basit bir şekilde bakıcak olursak aslında belirli bir veri setine ulaşırken veriye erişim yönetemimizin etkinliğini ne kadar donanım kaynağı tükettiğine bakarak karar vermek uygun yöntemlerden biri. Döndürdüğü satır başına en az donanım kaynağı tüketen yöntem aslında en etkin yöntemdir demek çokta yanlış bir önerme olmayacaktır.

2-)Etkin Yöntem Hızlı Olan Yöntemmidir? Bu madde aslında çoğu kez developerları yanıltan ve üzerinde tartışılması gereken bir madde. Hızın aynı zamanda etkinlik olarak kabul edildiği bir IT dünyasında yaşıyorsakta, donanım kaynaklarımız sınırsız değil. Bu bağlamda veriye erişirken kullandığımız en etkin yöntem her zaman en hızlı olan yöntemlerden biri olmayabilir. Oracle’ın Parallel processing yeteneklerini kullanıp sorgu sonuçlarımızda iyi response time’lar elde edebiliriz ancak, burada önemli olan nokta bu hızı ne kadar kaynak harcayarak yaptığımızıdır. Etkin veri erişim yöntemi, tüm sistem düşünüldüğünde SQL statementımızın daha az kaynak kullanarak (çünkü kaynaklar sınırlı), daha fazla ölçeklenebilir ve hızlı sonuçlar üretebilmesidir. Burada parallel processing’in DBA’in izin verdiği ölçüde sistemin tüm available kaynaklarını tüketme eğiliminde olduğu unutulmamalıdır.

3)Resoruce Utilization: Dönen satır sayısı ile doğrudan ilgilidir. Basit bir mantıkla dönen satır sayısı az ise resource utilization az, dönen satır sayısı çok ise resource utilization çoktur. Ama burada ana metrik dönen 1 satır sonucunda ne kadar kaynak kullanıldığının kontrol edilmesidir.

Bu 3 maddeyi tartışmaya başladığımızda söylediğim gibi, kaynak tüketimi bize etkin veri erişimi yöntemi bulmamızda yardımcı olan en önemli metrik olduğunu söylemiştik. Şimdi bu kouya biraz derinlemesine inelim.

İdeal hayatta, database engine tarafından yapılan kaynak tüketimi 4 başlık altında ölçümlenebilir. Bunlar CPU, Disk, Memory, Network ancak bu 4 parametre değerini toplayıp ölçümleyip değerlendirmek her bir SQL statementımız için oldukça zaman alıcı olabilir. Burada CPU’da bir satırın işlem görme süresi kullanılan CPU’ya bağımlı olarak değişkenlik gösterdiğinden bu parametre üstünden yorum yapıp efficent access path’e gitmek oldukça zor olabilir (çünkü sistemden sisteme değişkenlik var CPU anlamında). Kullanılan memory miktarı döndürülen satır sayısına oranla değişebilir bazı durumlarda bilgiler doğrudan memory’den okunacağından dolayı network ve disk kaynakları her zaman kullanılmayadabilir. Uzun süren bir SQL’in hiç disk ve network kaynağı kullanmadan mütevazı bir memory kullanarak çalışıp sonuç döndürmesi aslında sıradan bir olaydır. Ancak Database engine’in işini etkin bir biçimde bitirebilmesi için bir çok şey söyleyebilen, toplaması ve değerlendirmesi kolay bir parametre var oda sorgunun yaptığı Logical Read sayısıdır.
Şimdi Logical Read sayısının nasıl bulunduğuna ve nasıl değerlendiriliceğine gelilim.

Logical Read: SQL çalıştığı esnada, buffer cache(Main memory) üzerinde bir block’a erişme durumuna logical read denir. SQL çalıştığı esnada buffer cache’den okunan blok sayısıda o sorgu için yapılan logical read sayısını gösterir. Bu parametreyi elde etmek ve değerlendirmek yukarıda bahs ettiğimiz yöntemlere göre çok daha kollaydır. Logical Read sayısı bize, çalıştırdığımız sorgumuzun kullandığı veri erişim yönteminin etkiliğini söyleyebilir çünkü;

Lojik okuma sayısı CPU utilizationımız hakkında bize bilgi verir. Çünkü Lojik okuma CPU’yu meşgul eden bir işlemdir. Lojik okuma sayısının çok olmasından CPU utilizationımızında fazla olduğu genellemesine varabiliriz.

Lojik okuma, fiziksel disk okumalarına sebebiyet vereceğinden dolayı I/O sayımız hakkındada bize bilgi vermektedir. Lojik okuma sayımızın fazla olması, fiziksel okuma sayımızında artacağına işaret eder, buda fazladan I/O yapmak anlamına gelir. I/O’nun performansımızı negatif anlamda en çok etkileyen faktör olduğunu düşünürsek bu bağlamda veri erişim yönteminin etkinliği hakkında çok kritik bir bilgiyide bize sunmaktadır.

TroubleShooting Oracle Performance kitabının yazarı Christian Antognini’nin logical read hakkında, sorgularımız değerlendirirken yardımcı olacağını düşündüğüm şöyle bir yorumu var;

• Eğer sorgumuz dönen satır sayısı başına 5 lojik okuma yapıyorsa veri erişim yöntemimiz performanslıdır.
• Eğer sorgumuz dönen satır sayısı başına 10 ile 15 arasında lojik okuma yapıyorsa veri erişim yöntemimiz kabul edilebilir seviyededir.
• Eğer sorgumuz dönen satır sayısı başına 15 ile 20 arasında veya daha fazla lojik okuma yapıyorsa veri erişim yöntemimiz performansızdır ve iyileştirmeye ihtiyacı vardır.

Şimdi sorgumuzun yaptığı Logical Read sayısını nasıl görüntüleyeceğimize bakalım; (Aşağıdaki kodlardynamic performance view ları görebilen bir user ile yapılmalıdır ben SYSDBA yetkisi olan bir user ile çalıştım.)

ALTER SESSION SET STATISTICS_LEVEL = ALL;
/
SELECT * FROM HR.JOB_HISTORY
/
SELECT sql_id
FROM v$SQL
WHERE sql_text = ‘select * from HR.JOB_HISTORY’
/
SELECT *
FROM TABLE (
DBMS_XPLAN.DISPLAY_CURSOR (‘c8k95cqxkgh3b’, 0, ‘RUNSTATS_LAST’));

Yukarıda yapılan işlemi kısaca anlatmak gerekirse; ilk etapta session’ın istatistik seviyesini all’a çektim. Bundan sonra sorgumu yazdım ve çalıştırdım. Daha sonra sorgumun execution planını elde etmek için v$sql tablosundan sql_id sini aldım ve bir altta execution_plan’ı görüntülemek için yazdığım sql’de yerine koyup execution planı elde ettim.

Image

Evet sonunda execution planımızı elde ettik ve logical read sayımızı gördük. Yukarıda Christian Antogninin yapmış olduğu önermeyi dikkate aldığımızda, 7/10 <=5 olduğunu görüyoruz. Yani veri erişim tekniğimiz 5 ten bile küçük olduğu için etkin bir yöntem olduğu kararı verebiliriz.

Şimdi aynı sorgu üstünde farklı access path’ler ile lojik okuma sayılarının nasıl değiştiğini bir örnek ile inceleyelim.

Employees tablosuna önce full table scan yaparak,, sonrada employee_id üstündeki index’i kullanarak erişelim

SELECT /*+ full(emp) */
*
FROM HR.EMPLOYEES emp
WHERE employee_id = 102

Image

SELECT /*+ index(emp) */
*
FROM HR.EMPLOYEES emp
WHERE employee_id = 102

Image

Evet sorgu tipimizin eşitlik içermesi ve sorguladığımız kolon üstünde index olması erişim performansımızı yaklaşık 3 kat gibi bir oranda daha az lojik okuma yapmamızı sağladı. Bu örnekte asıl odaklanmamız gereken nokta farklı access pathlerde lojik okuma sayılarında büyük değişimlerin olabileceği olmalı. Yazının ilerleyen bölümlerinde index’li erişim ve full table erişimin ne tarz durumlarda yapıldığına daha detaylı değineceğim.

Yukarıda bir etkin yöntemle veriye eriştik birde etkin olmayan bir yöntem kullanarak veriye eriştik, peki etkin olmayan veri erişim yöntemlerinin seçilmesindeki nedenler ve bunların çözümleri nelerdir?

Nedenler

Okuma yaptığımız tabloda etkin erişebileceğimiz bir yapı yoktur. (Örneğin İndex gibi. Mesela yukarıdaki örnekte employee_id üstünde index olmasa idi full table scan yapmaya mecbur kalacaktık)

Uygun bir veri erişim yapısı mevcuttur ancak yazdığımız SQL bu uygun yapıyı kullanmaya müsait değildir.(Yukarıda verdiğimiz örnekte yazdığımız SQL’e full hinti vermiştik, bu şartlar altında employee_id üstünde index olmasına rağmen index kullanılmadı. Bunun nedeni tamamen yazdığımız SQL’den kaynaklı)

Eriştiğimiz tablo veya üzerinde dolaştığımız index partitionlı değildir.

Erişim yöntemini belirleyen optimizerın obje üzerindeki istatistiklerin eksikliğinden kaynaklı yanlış veri erişim yöntemini seçmesi.

Çözümler

Lojik okuma sayısını düşürmeye çalışmak.

Tabloda uygun erişim yapısı yoksa, bu erişim yapısını yaratmak (index gibi) veya tablonun fiziksel tasarımını değiştirmek(partitionlamak gibi)

Obje (Tablo) istatistiklerini her zaman güncel tutup, optimizer’ın doğru veri erişim yöntemini seçmesini sağlamak.

Sorgularımızı iyileştirmek için Selectivity parametresine göre, zayıf ve güçlü olarak gruplayıp uygun veri erişim yöntemini seçmek.

Selectivity

Selectivity çalıştırdığımız sorgumuz sonucunda dönen satır sayısının, toplam satır sayısına oranı olarak düşünebiliriz.

Formülüze Edicek olursak: (number of return rows) / (total rows)

Selectivity bir sorgunun nekadarlık bir kayıt döndüreceği hakkında bilgi söyleyen ve optimizer’ın bu bilgiye bakara hangi erişim yöntemini seçmesi gerektiğine karar verdiği bir parametredir. Selectivity’yi 0-1 sclasında düşündüğümüzde 0’a yakın durum güçlü selectivity, 1’e yaklaştıkça zayıf selectivity olarak kategorize edebiliriz.

Image

Şimdi, yukarıdada bahsettiğimiz 2 kategori ve bu kategoriler içinde kullanmamızın uygun olduğu etkin veri erişim yollarını listeleyelim.

Weak(Zayıf) Selectivity(dönen satır sayısının çok olduğu durum. 1’e yakın hal)

– Full Table Scans

– Full Partition Scans

– Full Index Scans

Strong(Güçlü) Selectivity(dönen satır sayısının az yada tek olduğu durum. 0’a yakın hal)

– Rowid Access

– Index Access

– Single Table Hash Cluster Access

Evet yukarıdakategorizasyonu yaptık ve kullanılabilecek uygun yöntemleri bu başlıklar altında grupladık. Sorgularımızda selectivty’i tahminleyebildiğimiz zaman ne şekilde erişim yapılması gerektiği konusunda fikrimiz olacak ve execution plana bakarak Oracle’ın nasıl bir yöntemle eriştiğine bakıp gerekli ise duruma müdahale edebileceğiz.

Bu yazıda veriye etkin erişim yöntemlerinin önemini anlatmak ve farkındalık yaratmak için güzel bir giriş yaptık. Bu yazıyı takip edicek yazılarda yukarıda grupladığımız yöntemleri ayrı ayrı inceleyeceğiz.

Kaynaklar:

TroubleShooting Oracle Performance, Christian Antognini, 2008

“Expert Oracle Database Architecture 2011″, Tom KYTE

tahiti.oracle.com

docs.oracle.com

Advertisements

About ... from Emrah METE

Bilgisayar Mühendisi
Aside | This entry was posted in Oracle, Uncategorized and tagged , , , , , , , , , , , , . Bookmark the permalink.

4 Responses to Veriye Etkin Erişim Yöntemleri – 1

  1. Pingback: Veriye Etkin Erişim Yöntemleri – 2 | Emrah METE

  2. Pingback: Veriye Etkin Erişim Yöntemleri – 3 | Emrah METE

  3. Pingback: Sorgu Optimizasyonu için Çalışma Zamanı İstatistiklerinin İncelenmesi | Emrah METE

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s