1

Konu: sql database için hangi pşanı önerirsiniz ?

çok kayıt almasını beklediğim 2 tablom var.
program içerisinde sürekli 2.tabloya kaydedilmemiş 1. tablo sorgusu yapıyorum.

2 ayrı mimari kullanabilirim, hangisini öneririsiniz ?

A.
tablo1 -> id_alan, bilgi_alan
tablo2 -> id_alan, bilgi_alan

SELECT * FROM tablo1 WHERE tablo1.id_alan NOT IN (SELECT tablo2.id_alan FROM tablo2)

B.
tablo1 -> id_alan, bilgi_alan, işlem_tamam (bit)
tablo2 -> id_alan, bilgi_alan

SELECT * FROM tablo1 WHERE işlem_tamam = 0
-----
sorgu her seferinde (yıllık her iki db de ayrı ayrı 1.500.000 kayıttan) 100-200 arası sonuç döndüreceğini düşünüyorum. bit olarak alan eklenmesi halinde de yılda 2MB yük olacak gibi

aklıma gelen B planı hız için db ye gelecek 2MB yükü gözardı etmek gibi 
A planının hızlı daha hızlı olabileceğini düşünüyorum, ne kadar fark eder ?

VFP9 SP2

2

Re: sql database için hangi pşanı önerirsiniz ?

Ali Abi;

Eğer iki tablonda da çok kayı olmasını bekliyorsan, SQL tümcesinde SELECT ............... WHERE IN ( Select .. ) Kalıbını kesinlikle unut. Performans açısından bu tip yoğun işlem gören tablolarında JOIN kullan :

Select ;
        ....  ;
    From Tablo1 ;
    ( Left / Right / Inner ) Join Tablo 2 ;
                        On Tablo1.PK1 = Tablo2.PK2
    WHERE .....

Eğer Primary Key seçimini indexler için doğru yapalirsen, ( yada WHERE clause için  doğru bir primary key index oluşturabilirsen ) kayıt sayısının büyüklüğünü o kadar dert etme bence.

Uğur
-------------------------------------------------------------------------------------------------------------
Hayat bir bisiklete binmek gibidir. Pedalı çevirmeye devam ettiğiniz sürece düşmezsiniz. Claude Peppeer
Kusuru söylenmeyen adam, ayıbını hüner sanır.  Türk Atasözü

3

Re: sql database için hangi pşanı önerirsiniz ?

ben WHERE bölümünü bulamadığımdan sordum.

aşağıdaki pek mantıklı gelmiyor:
SELECT tablo1.bilgi_alan FROM tablo1 LEFT JOIN tablo2 ON tablo1. id_alan=tablo2. id_alan
WHERE tablo2.bilgi_alan IS NULL

şimdi denedim, çalıştı - o zaman performans hakkında yorum yapmalı...

Son düzenleyen, konuka (27.02.2010 11:08:59)

VFP9 SP2

4

Re: sql database için hangi pşanı önerirsiniz ?

Ali abi, bildiğim kadarı ile JOIN in SQL performansı;  IN  den çok daha yüksek. Özellikle IN clause çok fazla değer içeriyorsa

Ayrıca

SELECT tablo1.bilgi_alan FROM tablo1 LEFT JOIN tablo2 ON tablo1. id_alan=tablo2. id_alan AND  tablo2.bilgi_alan IS NULL

kullanabilirsin.

Fikir jimsastiği açısından bir yöntem daha düşünebilirsin :

BIGINT -> 1. Tablonda AutoInc bir field tanımlarsın. Her ekleme işleminde otomatik artar.  Tablo2 ye  her aktarma yaptığında; Tablo1 in AutoInc değerini ayrı bir yerde tutarsın. Aktarım yapıyorken de sadece BIGINT column a göre basit bir WHERE ile sonuç alabilirsin

Son düzenleyen, ugurlu2001 (27.02.2010 11:08:54)

Uğur
-------------------------------------------------------------------------------------------------------------
Hayat bir bisiklete binmek gibidir. Pedalı çevirmeye devam ettiğiniz sürece düşmezsiniz. Claude Peppeer
Kusuru söylenmeyen adam, ayıbını hüner sanır.  Türk Atasözü

5

Re: sql database için hangi pşanı önerirsiniz ?

NOT IN (SELECT ...)  veya WHERE EXIST gibi sorgular tablo1 de olup tablo2 de olmayan yada , tablo1 de olan ve tablo2 dede olan kayitlari bulabilmek gibi amaclar icin kullaniliyor ornegin bir tablodan diger tabloya veri guncellemesi (basit replication diyelim)

Visual Fox Pro
1

select * from tabloA where TabloA.Pkey not in (select * TabloB.Pkey from TabloB) Where...

gibi...

Ugur'un dedigi 2 gibi 2 tabloda veri toplamak icin JOIN daha pratik ve hızlı ayrica where icin kullanilan key ler indexli ise daha da hizli performans elde etmek mumkun oluyor.

http://www.soykansoft.com/images/twitter.jpghttp://www.soykansoft.com/images/wp.jpghttp://www.soykansoft.com/images/blogger.jpg

6

Re: sql database için hangi pşanı önerirsiniz ?

Soykan abi;

WHERE IN kısmında Primary Key bile olsa; içteki her bir değer için dıştaki tüm tablo baştan sona taranıyor. Eğer iki tablonunda Primary Key i üzerinden işlem yapılıyorsa hız açısından kayda değer bir performans alınabilir.  Bence 1,500,000 kayıt faktörünü akılda tutmak lazım.

Exist kalıbı içinde aynı durum söz konusu diye hatırlıyorum.

"Bence" en mantıklısı PK filedlar üzerinden Join leri yapmak.

Uğur
-------------------------------------------------------------------------------------------------------------
Hayat bir bisiklete binmek gibidir. Pedalı çevirmeye devam ettiğiniz sürece düşmezsiniz. Claude Peppeer
Kusuru söylenmeyen adam, ayıbını hüner sanır.  Türk Atasözü

7

Re: sql database için hangi pşanı önerirsiniz ?

ugurlu2001 yazdı:


WHERE IN kısmında Primary Key bile olsa; içteki her bir değer için dıştaki tüm tablo baştan sona taranıyor.

"Bence" en mantıklısı PK filedlar üzerinden Join leri yapmak.

evet bende ayni dusuncedeyim.

http://www.soykansoft.com/images/twitter.jpghttp://www.soykansoft.com/images/wp.jpghttp://www.soykansoft.com/images/blogger.jpg

8

Re: sql database için hangi pşanı önerirsiniz ?

Hangisi hizli olur kismi biraz akademik aradaki farklara bakinca.

SQL
1

SELECT * FROM tablo1 WHERE tablo1.id_alan NOT IN (SELECT tablo2.id_alan FROM tablo2)

yerine:

SQL
1

2
SELECT * FROM tablo1 

WHERE tablo1.id_alan NOT EXISTS (SELECT * FROM tablo2 WHERE tablo1.tablo2.id_alan = tablo1.tablo2.id_alan)

oneririm, daha hizli. Burada Join kullanmak bir fayda getirmez, eger bu sekilde bir islem olacaksa ( NOT Exists ) sec derim.

Aslinda bunlari soylemeden once nolur nolmaz diye 2000000 kayitla test ettim:

Not in - ile 3171 milisaniye
Join ile - 2859 milisaniye
Not exists - 2109 milisaniye

sonucta Not Exists en iyisi olsa da hepsi yavas. Isin ilginc yani tekrarlamalarda (cache devreye girince) Not In ve Not Exists hizlanirken, Join hala 2800 milisaniye uzerinde kaliyor. Garip ama en kotusu o cikiyor. Execution planlarini kontrol edince "NOT In" ve "Not exists" ayni execution planalrini kullanirken, Join'de bu plana ek olan bir 'filter' var ve %1 ek yuk getiriyor.

(Ben olayin ne oldugunu tam anlayamadan konusuyorum bu arada)

B plani cok daha efektif bence. Hicbir index olmasa bile (onu da denedim):

SQL
1

SELECT * FROM tablo1 WHERE işlem_tamam = 0


hizli, 171-506 milisaniye arasinda (cache nedeniyle tekrarlar daha hizli) ve execution plani cok efektif (basit bir tablo scan tum yuku alan kismi).

Isin daha da hizli olmasi icin kullanilabilecek iki yontem daha geldi aklima ve birisini test ettim. Birisi indexed view digeri parttioned tablo. Ben partition denedim. Sonuc 15-17 milisaniye ve execution plan clustered index seek kullaniyor.

Deneme icin test kodlari:

SQL
1

2
3
4
5
6
7
8
-- partition icin bit alani kullanilacak

-- 0 ve alti bir parttion'a geri kalani diger
CREATE partition FUNCTION myPF1 (bit)
AS range LEFT FOR VALUES (0);
 
CREATE partition scheme myPS1
AS partition myPF1
ALL TO ([PRIMARY]);

Artik tabloyu yaratabiliriz:

SQL
1

2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE table1x 

 (bilgiID int identity,
 bilgiAlan varchar(50),
 islemTamam bit NOT NULL CONSTRAINT [DF_IslemTamam] DEFAULT (0)
 ) ON [myPS1] ([islemTamam]);
 
ALTER TABLE table1x WITH CHECK ADD
    CONSTRAINT [PK_BilgiID] PRIMARY KEY CLUSTERED
    (
        [islemTamam],
        [bilgiID]
    )  ON [myPS1] (islemTamam);

Artik partition tanimli tablo hazir. 2000000 test data koyalim:

SQL
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
INSERT INTO table1x (bilgiAlan, islemTamam)

SELECT TOP (2000000)
    CAST(newid() AS varchar(40)), 1
    FROM Master.sys.All_Columns t1
    CROSS JOIN Master.sys.All_Columns t2;
   
   
SELECT bilgiID, bilgiAlan INTO table2x FROM table1x;    
 
-- Buraya kadar esit icerik
-- 500 tane yeni farkli kayit
INSERT INTO table1x (bilgiAlan, islemTamam)
SELECT TOP (500)
    CAST(newid() AS varchar(40)), 0
    FROM Master.sys.All_Columns;

Yukaridaki kodun benzeri ile table1 ve table2 yarattim (partition yok onda).

Geriye de zaman test kodlari kaliyor (indexsiz islemTamam = 0 testini pas gecmis olduk):

SQL
1

2
3
4
5
6
7
8
9
SELECT * FROM table1 WHERE bilgiID NOT IN (SELECT bilgiID FROM table2);

 
SELECT * FROM table1 WHERE NOT EXISTS (SELECT * FROM table2 WHERE table1.bilgiID = table2.bilgiID);
 
SELECT * FROM table1 LEFT JOIN table2 ON table1.bilgiID = table2.bilgiID WHERE table2.bilgiID IS NULL;
 
SELECT * FROM table1 WHERE islemTamam = 0;
 
SELECT * FROM table1x WHERE islemTamam = 0;

Devami var ...

Son düzenleyen, cetinbasoz (27.02.2010 18:50:40)

Yen yaz 1907'ye yolla FB gelsin evinde yensin.
(sonra salaklar ciksin alin terine şike desin)

9

Re: sql database için hangi pşanı önerirsiniz ?

Bunlari soyledikten sonra, asil yapmak istedigini anlamaya calisiyorum. Tablo1 ve 2 yapi olarak ayni gorunuyor, sanki ikisinde de hep ayni veriler olacak ve arti olarak tablo1'de 100-200 tane daha kayit. Dogru mu anladim? Eger dogruysa tablo2'ye ne gerek var? Sadece IslemTamam ile tek tablo daha efektif olmaz mi? O zaman da bu bana dogrudan 'partitioned table' desteginin neden geldigini hatirlatiyor. Tabii boyle bir bit kolonundan cok, tabloyu musteriNo, islemTarihi ve benzeri ozelliklere gore parcalamak icin ortaya cikmisti (Dosya dolap cekmecelerinin A-Cd, Ce-Gh, ... Va-Zz gibi etiketlenmesine benzer bir islem. Tumune bakmak yerine Cetin ariyorsam dogrudan ikinci cekmeceye bakiyorum sadece).

Yen yaz 1907'ye yolla FB gelsin evinde yensin.
(sonra salaklar ciksin alin terine şike desin)

10

Re: sql database için hangi pşanı önerirsiniz ?

özellikle ilgiden dolayı çok teşekkür ederim.

1. tablo "fabrikada alanda bulunan tasnifsiz malları (yeni üretilmiş olanların makine çıkışında barkod verildiği andaki) - barkod numaraları;

2. tablo sonraki aşamada bu malları çeşitli konteynerlere tasnif edip saklanmasını kaydediyor yani ikinci tablonun yapısı aşağıdaki gibi:
paketid   konteynerid
1            1
2            1
3            1
4            2
5            2
6            3
...            ...

sorgunun amacı, bir paket bir konteynere kaydedilince (barkod okuyucu ile)
işçi onu fiziksel olarak koymazsa, başka konteynere konmasını önlemek....

Son düzenleyen, konuka (27.02.2010 23:58:15)

VFP9 SP2

11

Re: sql database için hangi pşanı önerirsiniz ?

Bana kizacaksiniz ama ben hala anlayamadim:) Yani niye 2 tablo gerekiyor.

MAL_ID, PAKET_ID, KONTEYNIR_ID, FIZIKSEL_FLAG, STATUS

vb tek tablo olmuyor mu.

Yen yaz 1907'ye yolla FB gelsin evinde yensin.
(sonra salaklar ciksin alin terine şike desin)

12

Re: sql database için hangi pşanı önerirsiniz ?

cetinbasoz yazdı:

siniz

buraya alınganlık yapabilirim smile
iki değil hatta 3 tablo var çünkü tablolar o kadar yalın değil

1. paket - paketid dışında paketarih, paketnot, tekstilid, adet, kkpersonelid var
2. kont - kontid dışında kontarih, kontnot, irsaliyeno, kkpersonelid, fabrikadabölüm var

1de örneğin 3 tekstil oldu mu 3 kere lüzumsuz tekrarlanan paketnot, kkpersonel zaten var, hepsini tek tabloya getirdiğimde (ilk başta öyle idi), bu sefer lüzumsuz tekrarlanan kontnot,  irsaliyeno, kkpersonelid, fabrikadabölüm le olacak.,
Daha ötesi zaten bir de irsaliye lerin tablosuna bağlanacak ....

O nedenle 3. bir köprü tablosu oluşturdum. Bu başlık da oradan kopuyor, konteynıra girmemiş paket id leri arıyorum...

Bir makalede okumuştum, tekrarlanan kayıtlı tablolar 20-30 kaydı aşıyorsa, yavru tablo ile çöz diye ...
sevgiler- Ali

VFP9 SP2

13

Re: sql database için hangi pşanı önerirsiniz ?

Tamam simdi oldu. Ben de gereksiz yere 2 tablo ile tekrar oluyor diye bakiyordum. O zaman B plani derim:) Partition yapsan da yapmasan da en efektif o olur gibime geliyor.

Yen yaz 1907'ye yolla FB gelsin evinde yensin.
(sonra salaklar ciksin alin terine şike desin)

14

Re: sql database için hangi pşanı önerirsiniz ?

konuka yazdı:

...
Bir makalede okumuştum, tekrarlanan kayıtlı tablolar 20-30 kaydı aşıyorsa, yavru tablo ile çöz diye ...
sevgiler- Ali

o ne ki. sap bir stok kartı tablosunu bile birçok tabloya bölmüş. neden öyle yapmış bilmiyorum ama (vardır bi bildikleri) binlerce tablo var sisteminde ve boş şirket bile 80 gb tutuyor.

Haksızlıklar karşısında susanlar, dilsiz şeytanlardır!
www.metinemre.com

15

Re: sql database için hangi pşanı önerirsiniz ?

Bu arada bir iki şey farkettim. - pek anlamlı olup olmadığını kestiremiyorum, paylaşayım

1.  SQL hiç index falan yapmasan dahi, sorgulamalara göre kendince bir index oluşturup, kayıtları düzenliyor gibi geldi ...

2.  VarChar 256 karakteri aşınca, VFP tarafına sorgu memo alanı olarak geliyor.
Yani sql memo karşılığı varchar(MAX) veya text değil, 256 den fazla olan her Varchar(xxx) memo oluyor.

VFP9 SP2

16

Re: sql database için hangi pşanı önerirsiniz ?

konuka yazdı:

Bu arada bir iki şey farkettim. - pek anlamlı olup olmadığını kestiremiyorum, paylaşayım

1.  SQL hiç index falan yapmasan dahi, sorgulamalara göre kendince bir index oluşturup, kayıtları düzenliyor gibi geldi ...
...

böyle bir yanılgıya düşme sakın. kayıtların çoğaldığında sorguların yavaşlar. sorguda kullandığın alanların gerektiği kadarını indekslemelisin. gerektiği kadarını nedir? mesela sorguda iki alan kullanıyorsun. birinciyle kayıtları 15-20 ye düşürdüysen ikinciyi indekslemen gerekmez.

Haksızlıklar karşısında susanlar, dilsiz şeytanlardır!
www.metinemre.com

17

Re: sql database için hangi pşanı önerirsiniz ?

NOT EXISTS / NOT IN / LEFT OUTER JOIN - ISNULL hakkında bu başlık ile ilgili bir makale.
Başlıktaki yorumların aksine NOT IN metodu hem en anlaşılır hem de en hızlı diye belirtiliyor indexli indexsiz karşılaştırmalar da var:
http://www.sqlservercentral.com/blogs/s … xists.aspx

If you need to find rows that don’t have a match in a second table, and the columns are nullable, use NOT EXISTS. If you need to find rows that don’t have a match in a second table, and the columns are not nullable, use NOT EXISTS or NOT IN.

The LEFT OUTER JOIN … IS NULL method is slower when the columns are indexed and it’s perhaps not as clear what’s happening. It’s reasonably clear what a NOT EXISTS predicate does, with LEFT OUTER JOIN it’s not immediately clear that it’s a check for non-matching rows, especially if there are several where clause predicates.

VFP9 SP2

18

Re: sql database için hangi pşanı önerirsiniz ?

Yanlis anlama var sanirim benim soyledigimde. Ben de not In ya da  not Exists daha hizli demek istemistim o 3'u arasinda. not In, not Exists arasinda ise ben yazim kolayligi acisindan not In, guvenilirlik ve hiz acisindan not exists diyorum. UniversalThread'de bir sure once bu tartisma olmustu ve orada ayni execution planlarini ve benim yaptigim zamanlamalari vermistim. Not In'in dezavantaji soz konusu kolon NULL kabul ediyorsa sonuclar hatali (yani bizim acimizdan hatali, ANSI SQL kriterlerini yazanlar ne dusundu bilmiyorum:)

Senin orijinal plan sorularin acisindan ise not in, not exists ya da left join B planinin yanina dahi yaklasamiyor performans acisindan (10-15 kez daha hizli).

UniversalThread'de tartisma uzadi gitti ve basta ben execution planlarinda bile Join'in ek yuk getirdigini ve en yavas oldugunu soylemistim,  sonuc ta ona baglandi. Orada postaladigim zamanlarala ilgili mesaj:


Ok I just tried for you:

                                                    t6       t5     t4     t3     t2      t1
Client processing time              0        0       0      0       0     16
Total execution time            2328 2296 3046 2250 2328 5937
Wait time on server replies 2328 2296 3046 2250 2328 5921

Two passes. t1,4 (LEFT), t2,5 (NOT IN), t3, 6 (Exists).

Yen yaz 1907'ye yolla FB gelsin evinde yensin.
(sonra salaklar ciksin alin terine şike desin)