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)