Herkese Selam,
Bu yazı dizisi kapsamında daha önce;
yazılarını paylaşmıştım. Veriye Etkin Erişim Yöntemleri – 2 yazısında selectivity’nin zayıf olduğu (1′e yaklaştığı) durumlarda veriye hangi metodlarla etkin bir şekilde erişebileceğimizi konuşmuştuk, bu yazıdada selectivity’nin güçlü olduğu (0′a yaklaştığı) durumlarda etkin erişim yönetemlerinin neler olduğu üzerinde konuşucaz. Umarım farkındalık anlamın faydalı bir yazı olur.

Selectivity’nin güç olduğu durumlarda etkin bir şekilde veriye eriştiğimiz yöntemlerin başlıcaları;
- Rowid Access
- Index Access
Şimdi sıra ile bu yöntemleri ve kullanım durumlarını detaylandıralım;
Rowid Access
Öncelikle Rowid kavramından kısaca bahsetmek istiyorum. Rowid en temel ifade ile, ilgili row’un database’deki adresini gösteren bir belirteçtir. Bu belirteç 10 byte’dır ve aşağıdaki alanlardan oluşmaktadır.

Örnektende anlaşıldığı gibi rowid 10byte’lık bir belirteç. Aynı zamanda Oracle’da pseudo bir kolon işlevide görmekte. Arzu ettiğimiz satırın rowid sinin select cümlesine rowid kolonunuda ekleyerek görebiliriz (select rowid, emp_no …). Yukarıdaki örnektende görüldüğü gibi bu numara kendi içinde bazı bilgiler taşımakta bu bilgileri ayrı ayrıda görüntüleyebilmekteyiz. Bunun için DBMS_ROWID paketini kullanabiliriz. Bunu daha iyi anlayabilmek için aşağıdaki örneği inceleyebiliriz.

Evet locations tablosunun her satırının rowid bileşenlerini incelediğimiz zaman datanın fiziksel anlamda bir arada durup durmadığınıda gözlemleyebiliyoruz. Yukarıdaki örnekte, aynı tablo içindeki tüm datanın aynı bloğa toplanmış olduğunu bu yöntem ile görebildik.
Rowid ile data erişimi selecttivity’nin güçlü olduğu durumda veriye en etkin erişimi sağlayan yöntemdir. Belirli bir satıra erişmenin en etkin ve efektif yolu rowid ile erişmektir. Ancak bu etkin yolu kullanabilmek için ilk başta rowid yi çekip saklamak gerekmektedir. Daha sonra bir sonraki aynı satıra erişimizimizde doğrudan bu bilgiyi kullanabilmekteyiz. İkinci erişimde rowid ile ilgili satıra gitmek ilgili satıra gitmenin en hızlı yöntemidir. Ancak burada satırın rowid’sinin değişmediği ve o süreç içerisinde değişmeyeceği garanti edilmelidir. Aksi takdirde ilgili rowid ye karşılık ilgili kayıt bulunamayacak ve işlem yapılamıyacaktır.
Rowid kullanabileceğimiz en sık durumlardan birisi, ekran geliştirilen projelerde kayıtların update edildiği ekranlar olacaktır. Bu ekranlarda ilk etapta kayıdı getirmek için select atarız ve bu select içerisine birde rowid kolonunu ekleriz. Daha sonra update işlemini yaparken update işlemini çektiğimiz rowid üzerinden yaparak, yaptığımız işlemi oldukça hızlandırabiliriz. Aşağıdaki örnekten bu durumun kullanımını inceleyebilirsiniz.
Önce Update edilecek kayıt DB’den rowid si ile beraber çekilir
SELECT ROWID, first_name, last_name, department_id, start_date, salary,
contractor
FROM employee_comp
WHERE emp_id = 200;
Kayıt formda gösterilir
Şimdi update işlemi yapılmak için form submit edilir ve veriye erişim rowid üzerinden gerçekleştirilir.
UPDATE employee_comp
SET salary = 10000
WHERE ROWID = ‘AAAPecAAFAAAABSAAA’
Yukarda gösterdiğimiz örnek rowid’nin en sık kullanılabileceği durumlardan biridir. Buna benzer case’lerimizin olduğu her yerde dataya en etkin şekilde rowid ile erişebiliriz.
Index Access

Selectivity’nin güçlü olduğu durumlarda index ile veriye erişmek, veriye erişimde en sık kullanılan yöntemdir. Çünkü index ile veriye erişmek, logical read sayımızı ve bunun sebebiyet vereceği physical read sayısını oldukça düşürecektir. Selectivity’si strong olan veriye index ile erişmek, veriye erişim hızımızı ciddi şekilde etkilemektedir. Bu durumu bir örnek ile inceleyelim.
Öncelikle bir tablo yaratalım ve içine 1 milyon kayıt insert edelim;
CREATE TABLE ind_deneme(col NUMBER,col2 VARCHAR2(50));
/
BEGIN
FOR i IN 1 .. 1000000
LOOP
EXECUTE IMMEDIATE ‘INSERT INTO ind_deneme
VALUES (:1,”IND_DENEME_X”)’
USING i;
END LOOP;
COMMIT;
END;
Şimdi tablomuza index atmadan selectivity’si düşük olacak bir sorgu çalıştıralım ve çalışma zamanı ile beraber execution plan’nına bakalım.
SET timing on
SET autotrace on
SELECT *
FROM ind_deneme
WHERE col < 5000;
– Sonuç
4999 rows selected.
Elapsed: 00:00:03.36
Execution Plan
———————————————————-
0 SELECT STATEMENT Optimizer Mode=ALL_ROWS (Cost=901 Card=36 Bytes=1 K)
1 0 TABLE ACCESS FULL IND_DENEME (Cost=901 Card=36 Bytes=1 K)
Evet şimdi aynı sorguyu col kolonuna index atıp tekrar deneyip sonucu gözlemliyelim.
CREATE INDEX ind_col ON ind_deneme(col);
– Sonuç
4999 rows selected.
Elapsed: 00:00:02.05
Execution Plan
———————————————————-
0 SELECT STATEMENT Optimizer Mode=ALL_ROWS (Cost=19 Card=2 K Bytes=97 K)
1 0 TABLE ACCESS BY INDEX ROWID TTDE_BILLING.IND_DENEME (Cost=19 Card=2 K Bytes=97 K)
2 1 INDEX RANGE SCAN IND_COL (Cost=9 Card=2 K)
Evet sorgunun selectivity’nin düşük olduğu durumlarda index kullanarak veriye eriştiğinde daha hızlı ve efektif sonuçlar ürettiğini görmüş olduk. Ancak istisnai durumların varlığını sorgularımızı yazarken mutlaka göz önünde bulundurmamız gerekir.
Index kullanımı oldukça sık kulanılan veri erişim yöntemidir ancak, çalıştırdığımız sorgunun karakteristiği performansı oldukça etkilemektedir. Örneğin tablo içindeki data’nın büyük bir çoğunluğunu çekmeye çalışan sorguda index kullnarak veriye erişmeye çalışmak sistem performansını drastic bir şekilde düşürecektir. Önnceki yazılarımdada değindiğim gibi bu tarz durumlarda erişim metodumuzun full table access olması performansımızı arttıracaktır.
Index li erişimin performansını etkiliyen durumlardan biride clustering factor’dür ancak bu konu özelinde bu durumu anlatmak yazıyı oldukça sıkıcı bir hale getireceğinden bu konuyu başka bir yazıya bırakıyorum ancak fikir edinme açısından aşağıdaki link okunabilir.
http://www.dba-oracle.com/art_index_clustering_factor.htm
Index’li erişim özellinde çok kısa Index Organized Table‘lardan bahsedicem. Index Organized Table’ların ana fikri tablo segmentlerini okumaktan kaçınmak çünkü index segmentleri tablo segmentlerinden daha küçüktür. Buda daha az lojik okuma yapmamız anlamına gelmektedir. Eğer P.K üzerinden sıkça sorgu yaptığımız bir tablo durumu söz konusu ise ve bu tablodaki data karakteristiği indexli bir şekilde tutulmaya elverişli ise bu tabloyu IOT formatında tutmak performansı artırır. Böylelikle data hep clustered olarak saklandığından pk üzerinden yapılan range scan sorgulamaları çok efektif ve etkili çalışır. Data primary key üzerinden organize edilmiş bir şekilde tutlduğu içinde olası bir order by işlemi çok hızlı sonuç döndürür.

Şu kısıma kadar anlattığım kısım Oracle’ın B-Tree index altyapısı ile çalışan mekanizmasıydı. Ancak Oracle’ Bitmap Index adı altında bu ürünü rakiplerine göre üstün kılan bir index yapısı daha mevcut. Kısaca bitmap indexler içinde bir kaç cümle söylnemek gerekirse;Bitmap indexler DWH sistemlerinde kullanılmaya oldukça müsait index yapılarıdır. Distinct value değeri sınırlı olan kolonlar üzerinden yapılmalıdır. Cardinalty si düşük bir kolonum varsa ve tablomda çok büyükse, bitmap index btree index e göre daha performanslıdır. Ancak sorguda birden çok or lu and condition ının birleşmesi gerekliki bitmap indexin performansı artsın.
B-tree ve Bitmap index mekanizmasının karşılaştırıldığı güzel bir makale var. Bu makale ile durumu daha iyi anlayabilirsiniz. Bitmap Index vs. B-tree Index: Which and When?
Bu yazıda selectivity’nin güçlü olduğu sorgularda hangi yöntem ile veri erişiminin ne denli avantaj getirdiği ve entkin veri erişiminin nasıl olduğunu paylaştım. Umarım farkındalık anlamında başarılı bir yazı olmuştur.
Kaynaklar
TroubleShooting Oracle Performance, Christian Antognini, 2008
“Expert Oracle Database Architecture 2011″, Tom KYTE
http://docs.oracle.com/cd/E14072_01/server.112/e10713/indexiot.htm
http://docs.oracle.com/cd/B10501_01/server.920/a96524/c13datyp.htm#918
http://www.orafaq.com/wiki/ROWID
http://www.oracle.com/technetwork/articles/sharma-indexes-093638.html