Gerekli alanlarin indexli olmasinda fayda var (sanki kimse bilmiyormus gibi:). Pratik kurallar:
-Index deyimleri kucuk olsun ki indexin fiziksel boyu kucuk olsun.
-Cok kullanilan sorgular icin indexlerin olsun, ama tuz gibi fazlasi zarar. Fazlasinin zararli olma nedeni:
Foxpro sorguyu yaparken once where ile mevuct indexlere bakiyor, server'dan indexi lokale indiriyor ve indexler karsilamiyorsa da kendisi gecici indexler yaratiyor. Bicak sirti bir is, hic yapmazsan o gecici indexleri olusturmakla vakit kaybedecek, cok yaparsan indexin fiziksel boyutu buyuyor.
-Indexin where'deki deyimle birebir uyusmasi lazim, yoksa ayni isi gorecek indexi kullanacak kadar akilli degil:) Ornek:
Soyad c(10), Ad c(10) ... tablon var. (SET ANSI varsayilan degerinde - OFF, ben hic ON yapmiyorum)
Visual Fox Pro
index on upper(soyad+ad) tag isim
diye de indexin.
Visual Fox Pro
lcSoyad = 'BASOZ'
select * from tablom where soyad = m.lcSoyad
Pekala isim indexi kullanilarak halledilebilir. Ancak VFP'ye gore buna uyan bir indexin yok. Uyan sekli:
Visual Fox Pro
lcSoyad = 'BASOZ'
select * from tablom where upper(soyad+ad) = m.lcSoyad
bu ise mevcut indexi kullaniyor. Kullanmasinin nedeni indexin "imzasina" tipatip uyan bir where deyimi var ve VFP'de (upper(soyad+ad) sonucu):
"BASOZ CETIN"
"BASOZCETIN"
"BASOZEFECAN"
"BASOZTEKIN"
"BASOZ EFECAN"
hepsinde = "BASOZ" sonucu .T. (ANSI OFF, bu nedenle sadece kisa olan karakter dizisinin boyu kadar kisim karsilastiriliyor ve BASOZ sonrasina bakilmiyor, BASOZ ile baslayan anlaminda bir sorgu).
Visual Fox Pro
* SQL
"BASOZ" = "BASOZ EFECAN" && .T.
"BASOZ EFECAN" = "BASOZ" && .T.
* SQL disinda
? "BASOZ" = "BASOZ EFECAN" && .F.
? "BASOZ EFECAN" = "BASOZ" && .T.
Dikkat edilmesi gereken SQL'de karsilastirma, SQL disindakinden farkli. Bunun nedeni SQL'de kural, "=" isaretinin sag ve solundaki deyimler yer degistirse de sonuc ayni olmali (asagida customer.cust_id ile ornek var bu kural icin).
Visual Fox Pro
select * from customer where cust_id = "ALFKI XXXXX"
select * from customer where "ALFKI XXXXX" = cust_id
SQL ile "tam karsilastirma istediginizde kullanmaniz gereken "=" yerine "==" operatoru. Bunun da davranisi SQL disindakinden farkli. SET EXACT, SQL'de hic bir etkiye sahip degil. Onun yerine SET ANSI var (SET ANSI ON, SET EXACT ON gibi, OFF'da OFF:). Ancak benim kullandigim SET ANSI yerine "==". O anki SET ANSI ne olursa olsun "X == Y", "X ve Y sonlarinda olabilecek bosluklar atildiktan sonra biribirine tam olarak esit mi" anlaminda. Yani sonlarindaki bosluklari hesaplamaya, ALLTRIM() gibi garip yontemlerle atmaya calismaya hic gerek yok:
Visual Fox Pro
select * from customer where cust_id == "ALFKI "
select * from customer where cust_id == "ALFKI"
Cust_id 6 karakter hatirladigim kadariyla degilse de oyle kabul edin:) Iki durumda da bosluklar atilarak karsilastiriliyor. ALLTRIM()'in where ile kullanimi anlamsiz yani (tek amaci soldan bosluk atmak olabilir, onun icinde diger dillerde de mevcut olan LTRIM() var, hem de kullanim amacini kodda net bir bicimde gosterir). Sirasi gelmisken ALLTRIM() indexte de kullanilmasi anlamsiz bir fonksiyon.
Integer keyler icin bintoc() kullanmanizi oneren yazilar okumussunuzdur. Integer 4 byte, bintoc() sounucu da 4 byte. O zaman neden bintoc()? VFP'nin compact index olusturma sirlari devreye girdiginden:) Cok kisaca acilamak gerekirse, compact indexler nodlar halinde, bir sonraki nodu yazarken tumunu yazmak yerine "oncesinden X byte + bilmemne" gibi yaziliyor. Stringler ile:
ADANA
ADIYAMAN
...
yazilirken ADIYAMAN icin 2IYAMAN yazilmasi gibi (cok cok kaba ornekleme - zaten ben de hic bir zaman tam olarak anlayamadim ki anlatayim:). Neyse anlatimi yediyseniz bintoc ile yapilinca -128...127 arasi ayni 3 karakterle basliyor, -32768...32767 ayni 2 karakterle vs Neyse bu cok teknik, bu kadar fazlasina ben hic dikkat etme geregi duymadim simdilik.
-Tablo daha once tumuyle okunduysa sorgular daha hizli. Ve tabloyu bir kez tumuyle cok hizli okutmanin yolu:
Visual Fox Pro
select tablom
scan
endscan
Cok basit ve hic birseye yaramayan kod gibi duruyor. Hiz duskunlerine tavsiye edilir:)
-Tablo exclusive kullanilabiliyorsa daha hizli (cursorler daima exclusive ve hic indexleri olmamamsina ragmen onlarda sorgular indexli tablolardan cok daha hizli olabilir - hele buyuk degillerse ve tamami hafizaya okunabildiyse).
-Shorcut (kisa devre) kurali. VFP, VB'nin aksine (VBciler kizmasin lutfen) C gibi kisa kisa devre kuralini uyguluyor ve bunu SQL'de de yapiyor. Kural soyle:
X ve Y && X yanlissa sonuc daima yanlis olacak Y'ye bakmaya gerek yok
X veya Y && X dogruysa sonuc daima dogru, Y'ye bakmaya gerek yok
X ve Y veya Z && (X ve Y) veya Z - ve oncelikli, sol affinite
* Karar verebilmek icin X'e bakacak, yanlis ise Y'e bakmasi gerekmiyor ama Z'ye bakmak zorunda.
Z veya X ve Y && olsaydi, Z dogru oldugu anda bakmay kesebilirdi
(cust_id = "ALFKI" and title = "Owner") or maxOrdAmt > 1000 && (X ve Y) veya Z
Buna indexlilere daha hizli bakilacagini eklerseniz, indexli olanlari da one koyan efektif ve/veya baglantilarinda sonuclar daha hizli.
-Codepage. Ozellikle VFP9 etkileniyor. Mevcut codepage, tablonun codepage'inden farkli ise string islemleri hatayi onlemek icin indexleri kullanmiyor ve islem cok uzun surebiliyor. Set EngineBehavior 70 ile eski arama motoru devreye sokulabilir bu durmlarda ama sonuclariniza dikkat edin. Ideali codepage'lerin tutmasi ( CPCURRENT() = CPDBF() ).
-Memo indexleme. Memolar normalde indexlenemez. Bazen adres, dosyaadi gibi seyler memoda tutulabilir. Onalr icin her zaman ise yarmayacak benium uydurdugum bir indexleme yontemi:
index on sys(2007, myMemo) tag memoindex && VFP9da sys(2007, myMemo, 1, 1) - 32bit
ile memonun icerigi yerine CRC degerini tutmak. Aradigimin ayni sekilde CRC (sys(2007)) ile degeriyle aramak ve tabii ki emin olabilmek icin asil degerleri karsilastirmak ( ne ilginctir ki SQL2005te de ayni yontemi kullaniyorlar:) Isin icine kisa devre kurali girdiginden sonuclar hizli:
Visual Fox Pro
lcAranan = "C:\PROGRAM FILES\FALAN FOLDER\FILAN DOSYA.JPG"
select * from tablom ;
where sys(2007,upper(myMemo)) == sys(2007,m.lcAranan) ;
and upper(myMemo) == m.lcAranan
Baska yontem aklima gelmiyor simdilik. VFP'nin tek rakibi THY:) (saka tabii, MSSQL, Oracle, DB2 ... ile yarisacak hali yok, kendi sinifinda ise hala rakipsiz).
Bu arada SELECT - SQL hizli vge cogu kez tercih edilecek olmasina ragmen, bazen onun yavas kaldigi scan...endscan kullanman gereken durumlar olabiliyor. O da senin kodunun optimizasyona ihtiyaci olan yerlere saklanacak seyler. Bununla ilgili Soykan'a takilayim biraz (Soykan kizma-tabii Intel kullananlar da kizmasin:)
Soykan, senin makine Intel galiba, AMDnin tozunu yutmaktan vazgecmiyor:) Son zamanlarda kullanmak durumunda kaldigim data boyutu diskte 250Mb idi, biraz data tipleriyle oynayinca 150Mb'a dustu. Kullanilan index de 23Mb. Toplam 802772 kayit. Icindeki bir alana gore 6 adet alanin N kere array'e alinmasi gerekiyordu (mecburen ayri ayri, onu isleyen bir C FLL nedeniyle). N=1274. Yani kabaca:
Visual Fox Pro
select distinct ControlField into cursor xx && 1274 kayit
scan
select f1 from anaTablo where ControlField == xx.ControlField into array a1
select f2 from anaTablo where ControlField == xx.ControlField into array a2
select f3 from anaTablo where ControlField == xx.ControlField into array a3
select f4 from anaTablo where ControlField == xx.ControlField into array a4
select f5 from anaTablo where ControlField == xx.ControlField into array a5
select f6 from anaTablo where ControlField == xx.ControlField into array a6
* result = CFLL(a1,a2 ... a6)
endscan
Kodun orijinali yaklasik 2-3 dk surerken son hali (ayaktaysan otur) 4.3 - 4.4 sn. Tabii sartlar:
AMD Athlon X24600, 2Gb RAM ve Select-SQL yerine biraz xBase scan..endscan.
Eger kendi makinesinde test etmek isteyenler olursa bir sekilde parcalayip bir yerlere upload edeyim:)
Ya ne bileyim, 98-100bin kayittan 2, 3, 4sn bana cok yavas gorundu. Tabii kisadevre kuralini pas gecmissin 2snlikte. Ha onu tekrar gozden gecirince bir baska uyari:
[A-001] yerine "A-001" ya da 'A-001' kullanin. Ayni gibi gorunseler de farklilar (bakiniz eski konular - [] icinde sabitler degerlendirilir ve hic beklemediginiz sonuclar alabilirsiniz, gozden kacirmak kolay, cozmesi zor olur).