8 Nisan 2013 Pazartesi

Dağıtık Sorgularda Performans İyileştirmesi ( DRIVING_SITE )


Bu yazıda sizlerle dağıtık sorguların performans iyileştirmesi ile ilgili driving_site hintinden ve kullanımından bahs edicem. Umarım farkındalık anlamında faydalı bir yazı olur.
IT dünyasında genellikle farklı veritabanlarında genellikle büyük boyutlu datalar üzerinde oldukça sık işlem yapıyoruz ve bu işlemlerimizi  OLTP ve OLAP sistemlerde dblink’ler aracılığı ile yürütüyoruz. Hepimizin deneyimlediği gibi farklı veritabanlarıdaki datalar üzerinden işlem yapılmaya başlandığı zaman araya network’ude koyduğumuzdan ötürü sorgu performanslarında bir miktar yavaşlama olduğunu görüyoruz. Bu yavaşlama network’e çıkardığımız data miktarı arttığında, lineer olarak performans üzerinde negatif etki yaratarak sorgunun dahada yavaşlamasına neden olmakta. Tek dblink üzerinden farklı makinadaki bir datayı paralel’de çekemiyeceğimizden ötürü performans anlamında yapacak çokta birşey kalmıyor. İşte tam bu noktada Oracle’ın driving_site hinti devreye girip dağıtık sorgu performansımızı geliştirmeye yönelik pozitif etki yapıyor. Bu etkiyi daha iyi ifade edebilme adına bu noktadan sonra örnekler ile ilerleyeceğim. Örnekleri Oracle 10g R2 sürümünde gerçekledim.
Öncelikle 2 Farklı Veritabanım var, ve B
Şimdi A ve B veritablarında tablo yaratıp örnek sorgu çalıştırıp performansı inceleyelim.
A--> Veritabanındaki İşlemler
CREATE TABLE departments(department_id INTEGER, department_name VARCHAR2(100));
INSERT INTO departments
VALUES (1, ‘finans’);
INSERT INTO departments
VALUES (2, ‘Satis’);
INSERT INTO departments
VALUES (3, ‘Uretim’);
INSERT INTO departments
VALUES (4, ‘Bilgi Islem’);
INSERT INTO departments
VALUES (5, ‘HR’);
COMMIT;
B --> Veritabanındaki İşlemler
CREATE TABLE musteri (musteri_no INTEGER, ad VARCHAR2(1000), departments INTEGER);
– Index kullanabilecegim bir sorgu yazmak istedigimden
–departments kolonuna index atiyorum.
CREATE INDEX ind_dep ON musteri(departments);
– Tablo içine 50 bin, departments kolonu 5 olan kayit ekledim.
BEGIN
FOR i IN 1 .. 50000
LOOP
EXECUTE IMMEDIATE ‘insert into musteri values(:1,:2,5)’
USING i, ‘ad_’ || i;
END LOOP;
COMMIT;
END;
– Tablo içine 1M, departments kolonu 1,2,3,4 olan kayıt –ekledim.
BEGIN
FOR i IN 1 .. 1000000
LOOP
EXECUTE IMMEDIATE ‘insert into musteri values(:1,:2,:3)’
USING i, ‘ad_’ || i, MOD (i, 4) + 1;
END LOOP;
COMMIT;
END;
Şimdi  A ve B veritabanında 2 tablo oluşturduk. A veritabanındaki departments tablosu bir lookup ve içeride toplam 5 kayıt var. B veritabanındaki müşteri tablosu oda bir lookup ve içinde 1050000 kayıt var. Şimdi A veritabanında aşağıdaki sorguları çalıştırıp sonuçları inceleyelim.
İlk etapta hiç hint kullanmadığımız yöntemde execution plan ile sorgu çalışma zamanına bakalım.
EXPLAIN  PLAN FOR SELECT a.ad, b.department_name
FROM musteri@myLink a, departments b
WHERE a.departments = b.department_id
AND a.departments = 5;
SET linesize 2000
SELECT *
FROM TABLE (DBMS_XPLAN.display);
notDrivingSet
Evet execution plan’dan da görüldüğü üzere yazdığımız sorgu karakteristiği gereği index kullanması gerekirken dblink ile erişim yaptığımızdan dolayı karşı taraftaki tablo datasının tamamını network’e çıkardı, datanın tamamını sorguyu çalıştırdığımız tarafa getirdi ve işlemi kendi local’imizde yaptı. Ayrıca dblink ile karşı tarafta bir tabloya bağlandığımız için local makinemiz karşı tarafın metadata’sından haberdar değil bu yüzden var olan index’ide kullanamadı. Şimdi sorgunun ne kadar sürede bittiğini görelim.
SET timing on
SELECT a.ad, b.department_name
FROM musteri@myLink a, departments b
WHERE a.departments = b.department_id   
AND a.departments = 5;
/*
 50000 rows selected.
Elapsed: 00:00:29.63
*/
Şimdi driving_site hintimiz’i yazarak execution plan inceleyip sorgunun ne kadar sürede bittiğini görelim.
EXPLAIN  PLAN FOR SELECT /*+ DRIVING_SITE(a) */ a.ad, b.department_name
FROM musteri@myLink a, departments b
WHERE a.departments = b.department_id
AND a.departments = 5;
SET linesize 2000
SELECT *
FROM TABLE (DBMS_XPLAN.display);
drivingSet
Evet execution plan’dan da anlasildigi uzere sorgumuz index kullanabildi. Bunun nedeni yazdığımız hint kaynaklı local’imizde bulunan küçük tabloyu karşı tarafa transfer edip işlemi karşı tarafta yapıp sonuç dataset’ini network’e çıkaraıp işlemi tamamladı. Böylelikle hem network üzerine ihtiyacımız olmayan dataları çıkarmadı hemde işlemi remote’da yaptığından dolayı index kullanabildi. Şimdi sorgumuzun performansına bakalım.
SET timing on
SELECT /*+ DRIVING_SITE(a) */
a.ad, b.department_name
FROM musteri@myLink a, departments b
WHERE a.departments = b.department_id AND a.departments = 5;
/*
50000 rows selected.
Elapsed: 00:00:20.80
*/
Evet sonuçlardan da anlaşıldığı üzere bu tarz case’lerde işlemi remote’da yaptırarak sorgu performansımızı oldukça iyi seviyelere çekebiliriz. Ancak hint yazmak riskli bir işlem olduğundan kullanmadan önce sorgumuzun karakteristiğini iyi incelememiz gerekmektedir. Aksi takdirde pozitif etki beklerken negatif sonuçlar elde edebiliriz.
Kaynaklar

Hiç yorum yok:

Yorum Gönder