Re: [Linux-programlama] MYSQL Sorgusunda istediğim sonucu alamıyorum

---------

New Message Reply About this list Date view Thread view Subject view Author view Attachment view

From: Serdar KÖYLÜ (serdarkoylu@fisek.com.tr)
Date: Thu 09 Dec 2004 - 10:25:47 EET


Selamlar..

Optimizasyon denen şey, her zaman her sorguda (mesela) en iyiyi veren
şey demek değil ki? Zaten kilit noktası burası. Her zaman en iyi olan
şey, optimizasyon değil, bir kural olur. Hatta bunu DB yazanlar
kendileri koyar sisteme.

Optimizasyon, belli durumlarda (ki bu tamamen veya büyük oranda
uygulamanın doğasına bağlıdır, veritabanı, programlama dili, kullanıcı
alışkanlıkları ileriye yönelik öngörüler vs.) istenen en iyi sonucu
vermek üzere kullanılır. Burada optimum durumu yakalamak için bir takım
işler yapılır. Hatta, bazı durumlarda bu işler tersine etki
gösterebilir. Optimizasyon bir bütündür, GUI'den başlar seçilen dosya
sisteminde biter. Ve aslolarak, öyle büyük, dudak uçuklatacak farklar da
yaratmaz. Ama bir kaç optimizasyon birleşir çoğu durumda gerçekten güzel
olabilir.

Şimdi verdiğimiz örneğe ve senin örnek datana bakalım.

f1=d1 or f2=d2 or f3=d3

Bu satır parse edilip işletirken, "or" işleminin doğası gereği, ilk
işlem doğru ise, takip eden karşılaştırma işlemleri yapılmaz. Buda benim
söylediğim optimizasyon örneğinin dayanağıdır. Şimdi senin datalara bir
bakalım:

>p1 p2 ve p4'ten 4'er tane, p3'ten 7 tane girdim tabloya.

p1 -> 4
p2 -> 4
p3 -> 7
p4 -> 4

Toplam : 19 Kayıt. Bu halde, bunların frekansları

p1 -> 4/19 -> 21%
p2 -> 4/19 -> 21%
p3 -> 7/19 -> 37%
p4 -> 4/19 -> 21%

Şimdi bu durumda, eğer f1=="p3" cond.u öne koyarsak,

f1="p3" or f1="p1" or f1="p2" or f1="p4"

İşlenen kayıtların
%37'sinde 1 or işlemi (1ms olsun).
%21'inde 2 or işlemi (2ms)
%21'inde 3 or işlemi (3ms)
%21'inde 4 or işlemi (4ms)

Hesaplarsak:
 7 * 1ms = 7ms.
 4 * 2ms = 8ms
 4 * 3ms = 12ms
 4 * 4ms = 16ms

Toplam, 43ms sürecek bu WHERE part için gereken işlemler.

Şimdi bu ne kadar optimizasyon. Dikkat edersek, f1="p3" kuralı, geriye
kalan %63 için bir tür bariyer oluşturuyor. Bu durumda başa bunu
koyarsan, sorgunun %63'ünde gereksiz yere 1 or işlemi fazladan
yapacaksın. Ama sona koyarsan, bu "en fazla" ama frekansı düşük olan
değer en son bakılarak sorguyu rahatlatacak mı, bakalım:

 4 * 1ms = 4ms.
 4 * 2ms = 8ms
 4 * 3ms = 12ms
 7 * 4ms = 28ms

Toplam 52 ms. Bak işte sana optimizasyon. Peki 2. Sırada koyarsak:

4 * 1ms = 4ms
7 * 2ms = 14ms
4 * 3ms = 12ms
4 * 4ms = 16ms

46ms etti bu kez. Asıl soru şu. Sistem her zaman aynı kondisyon içinde
mi bulunuyor? Çoğu zaman bir önceki sorgu bir sonraki sorgunun
sonuçlarını etkiler. Nasıl dersen, mesela cache'leri doldurur/boşaltır.
Mesela önceki sorgu bufferleri doldurur, sonra gelen hazır bulur vs.
Ayrıca, bu kadar kısa süren bir işlem esnasında makinede göremediğin bir
çok işlemde seni yavaşlatabilir. Her iki sorgu arasında makinenin aynı
interrupt, scheduling, L1/L2 Cache durumlarına sahip olduğunu öngörmek
zor. Sonuç olarak belki böyle 19 kayıt değil, 19bin kayıt olsaydı, bu
optimizasyon anlamlı olacaktı. Fakat, mesela, o zaman da Disk I/O ciddi
bir bootleneck olacak, onun şişirdiği zaman nedeniyle bu optimizasyondan
kazanacağınız mikrosaniyeler önemsiz olabilirdi. İşlem optimizasyonla 1
sn sürsün (=1000 ms, 1000000 mikrosn.), bu optimizasyonla atıyorum
50mikrosaniye kazanacaktınız. Peki bu tür bir optimizasyon nerede
faydalı olur?

Bir teknik serviste, 1 yıllık kayıt olsun. Bu kayıtların çoğu "TESLİM
EDİLDİ" durumunda olacaktır. Ancak 1-2 haftalık işlemler "PARÇA
BEKLİYOR", "HAZIR", "ARIZASI ARANIYOR" gibi başka durumlarda olacaktır.
Sonuçta kayıtların ilk 1 hafta %2'si "TE" iken, örneğin, 4 Ayda %90 "TE"
olacak, 9. Ayda %99 TE olacak. Eğer siz 1 yıl için optimizasyon
yaparsanız bu or işleminde, yılbaşında bu optimizasyon tersine
yavaşlatacak, ama mesela 3.Aydan sonra, 6.Aydan sonra işi
hızlandıracaktır. Bu bir öngörü. Ama sanırım sallama değil makul bir
öngörü. En azından benim servisimde böyleydi.

Burada programcılığın "analiz" damarına basmanız gerekir. Şimdi bir
haftada 20 iş alıyorsanız, bunların 15'ini 1 haftada yapıp, 3'ünü 1 ay
içinde yapıp, 1'ini 3 ay içinde yapıp, 1'ini hiç yapamıyorsanız, bu
güzel bir havuz problemi olur. Bir havuza vanadan haftada 20 ton su
giriyor. Bir başka vana haftada 15 ton su boşaltıyor. Bir diğeri 3 ayda
1 ton su boşaltıyor... yıl sonunda havuza giren toplam su miktarı,
havuzda biriken su miktarı...

Gördünüzmü havuz problemleri aslında ne kadar mantıklıymış :) "Eeeh, ula
genemi havuz problemi" derseniz, ne güzel çöpcü kardeşlerimiz hiç havuz
problemi çözmedikleri gibi şu anki hayatlarında da havuz problemi ile
uğraşmıyorlar. Her daim söylemişimdir, kafam çalışsaydı çöpcü olurdum.
Kısaca programcılık böyle bir zenaat, kafa kırmadan olmuyor.

Neyse, şimdi havuzumuzda 10000 kayıt olsun. Bunların 4. Ayda %90'ı (gibi
bir değer) "Teslim Edildi" olacak. Bunu hesaplayabiliyoruz istatistik
olarak. Bizim optimizasyon faydalı olacakmı:

%90 of 10000 = 9000 * 1ms = 9 sn.
%10 of 10000 = 1000 * 2ms = 2 sn.

Toplam sorgu en fazla 11 sn sürecek (daha doğrusu bu WHERE part için bu
kadar zaman kaybedecek). Tersine bakalım:

%10 of 10000 = 1000 * 1ms = 9 sn.
%90 of 10000 = 9000 * 2ms = 18 sn.

Sadece "a='b' or a='c'" gibi iki ardışık or işlevi olsa bile, toplam
27sn kaybedecek. 11 ve 27. Sizce bu optimizasyon faydalı mı?

Örnekten iyice görülüyordur sanırım. Optimizasyonlar, çoğu zaman, çoğu
durumda ince hesap gerektiren, sistemi, veri yapısını iyice analiz
etmeyi gerektiren bir konudur. Dahası her zaman iyi olan
optimizasyonlarda olmayabilir. Bizim örneğimiz, ilk haftalarda işi
yavaşlatan bir optimizasyon mesela.

Ama olmayan değerleri sorguya eklememek her daim doğru bir kuraldır.
Bunları karıştırmamak icap eder.

Sanırım optimizasyon denen şeyin ne zaman ve nasıl düşünülmesi gerektiği
ile benim bahsettiğim "yanlış kod" kavramı arasındaki farkı
anlatabilmişimdir.

Saygı ve sevgiler..

> On Wed, 8 Dec 2004, Serdar [ISO-8859-1] KÖYLÜ wrote:
>
> > SELECT * FROM HEDE WHERE f1=p1 or f1=p2 or f1=p3 or f1=p4
> >
> > Burada p3 ve p4 seçilmemişse, Bunları işleme koymak yanlıştır. Ama
> > optimizasyon derseniz, mesela, istatistik olarak veritabanında en fazla
> > sayıda olduğunu bildiğimiz f1 == p3 durumuna ait işlemin en başa konması
> > bir optimizasyon olabilir.
>
> Kesinlikle çok güzel bir örnek vermişsin:
>
> test=# SELECT version();
> version
> - --------------------------------------------------------------------------------------------------------------
> PostgreSQL 8.0.0rc1 on i686-redhat-linux-gnu, compiled by GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)
> test=# CREATE TABLE serdar (c1 varchar(10));
> CREATE TABLE
> test=# INSERT INTO serdar VALUES ('p1'); -- (Yanlis anlama Serdar :-) )
> INSERT 26117 1
> ...
>
> p1 p2 ve p4'ten 4'er tane, p3'ten 7 tane girdim tabloya.
>
> test=# EXPLAIN ANALYZE SELECT * from serdar WHERE c1='p3' OR c1='p2' OR
> c1='p1' OR c1='p4';
> QUERY PLAN
> - ------------------------------------------------------------------------------------------------------------------------------
> Seq Scan on serdar (cost=0.00..3.42 rows=4 width=33) (actual time=0.065..0.249 rows=19 loops=1)
> Filter: (((c1)::text = 'p3'::text) OR ((c1)::text = 'p2'::text) OR ((c1)::text = 'p1'::text) OR ((c1)::text = 'p4'::text))
> Total runtime: 0.458 ms
> (3 rows)
>
> test=# EXPLAIN ANALYZE SELECT * from serdar WHERE c1='p1' OR c1='p2' OR
> c1='p4' OR c1='p3';
> QUERY PLAN
> - ------------------------------------------------------------------------------------------------------------------------------
> Seq Scan on serdar (cost=0.00..3.42 rows=4 width=33) (actual time=0.036..0.222 rows=19 loops=1)
> Filter: (((c1)::text = 'p1'::text) OR ((c1)::text = 'p2'::text) OR ((c1)::text = 'p4'::text) OR ((c1)::text = 'p3'::text))
> Total runtime: 0.375 ms
> (3 rows)
>
> time kısmı bize Serdar'ın söylediğinin ne kadar doğru olduğunu gösteriyor.
>

_______________________________________________
Linux-programlama mailing list
Linux-programlama@liste.linux.org.tr
http://liste.linux.org.tr/mailman/listinfo/linux-programlama


New Message Reply About this list Date view Thread view Subject view Author view Attachment view

---------

Bu arsiv hypermail 2.1.2 tarafindan uretilmistir.