1

Konu: SQL SELECT'de indeksleme nasıl olmalı?

Merhaba,

İstenirse soruyu açmak için somut bir örnek de verebilirim ama; şimdilik sorum kısaca şu:

SQL SELECT ile tek bir tablonun birden çok field'ından koşulların sıralandığı bir komut düşünelim ve tablomuz 80-100 bin kayıttan oluşsun. Bu durumda bildiğiniz gibi SQL SELECT'in daha hızlı çalışması için tabloyu indekslemek gerekiyor. Bunun için genel kurallar ortaya konabilir mi? Örneğin koşulların bulunduğu her field için ayrı indeks oluşturulmalı gibi.
Ya da daha kısa olarak; SQL SELECT komutu kullanırken tablo indekslemesi nasıl olmalı?

Teşekkürler

2

Re: SQL SELECT'de indeksleme nasıl olmalı?

where den sonra kullanacagin alanlara ait index olmasinda fayda var ama her alanida indexleyemeyecegimize gore benim onerebilecegim sey

tablomuz test olsun

Visual Fox Pro
select * from test where .t. into cursor CrsTest nofilter readwrite

gibi bir komutla tablo kayitlarini cursore almak ondan sonrada where e konu olacak alanlari indexlemek
boylece sorgu surelerini kisaltirsin ancak ben 98.000 kayitli stok detay tablomdan

Visual Fox Pro
select * from stokdetay where .t.

  komutu ile 3-4 saniye gibi bir surede sorgu sonucu aldim ,

Visual Fox Pro
SELECT * FROM stokhd WHERE  [A-001] $ skodu AND fiskodu=[001]

gibi bir kodlada bu sure 2 sn yeye kadar dustu ...

ayrica

asagidaki kod rushmore optimization level for STOKHD table : none raporu verirken

Visual Fox Pro
LOCAL cmemvar

=SYS(3054,11,"cmemvar")
SELECT * FROM stokhd
WAIT WINDOW cmemvar

bu kod using index tag SKODU to rushmore optimize table STOKHD , rushmore optimization level for table STOKHD : full raporu verdi

Visual Fox Pro
LOCAL cmemvar

=SYS(3054,11,"cmemvar")
SELECT * FROM stokhd WHERE skodu=[A-001]
WAIT WINDOW cmemvar

buradan anlasilacagi uzere indexli alanlar üzerinde where ile yada join ile veri cekmek daha hızlı olmakta...

3

Re: SQL SELECT'de indeksleme nasıl olmalı?

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).

4

Re: SQL SELECT'de indeksleme nasıl olmalı?

cetinbasoz yazdı:

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).


Evet şu an ki makinam (laptop)  Intel işlemcili ama AMD nin performansini biliyor ve hak veriyorum smile

Visual Fox Pro
select tablom

scan
endscan

iyi tatktik smile

ornek verdigim kodda kisa devre kuralini nasil uygulariz ?

[] kullanma aliskanligi bende "" ve ' lari bazen goz iyi secemiyor ordan kaldi ama kullanim yerini iyi secmekte fayda var smile

5

Re: SQL SELECT'de indeksleme nasıl olmalı?

Dikkat.

select tablom
scan
endscan

Bu gerçekten işe yarıyor, bu şekilde veya benzer şekillerde bende kullandım.

Nereye kadar işe yarıyor derseniz.

Table lar büyükse ve/veya aynı anda çok sayıda table açıksa avantajı tamamen kaybediyorsunuz ve ilaveten "scan endscan" size ekstra zaman kaybettirmeye başlıyor. Tecrübeyle sabit, programlarınıza bunu koymaya niyet ederseniz müşterinin olabilecek data büyüklüklerini gözönüne almalısınız.

6

Re: SQL SELECT'de indeksleme nasıl olmalı?

Yanıtlar için teşekkürler. Her zamanki gibi çok öğretici.
Benim tablom şöyle:
YERTANI.DBF
yerkodu     Ch   4
tanikodu    Ch    5
biopsino     Ch   9
yil_ay        Ch   6
mg_kriter   Ch   1

Hemen hemen en sık kullanılacak ifade şu:

SELECT BIOPSINO DISTINCT FROM YERTANI WHERE YERKODU = m.YERKOD AND ;
TANIKODU = m.TANIKOD AND YIL_AY = m.cYil INTO ARRAY aTARA ORDER BY BIOPSINO

Şu ifade de 2. sıklıkta

SELECT BIOPSINO DISTINCT FROM YERTANI WHERE YERKODU >= m.YERKODALT AND ;
YERKODU <= m.YERKODUST AND TANIKODU = m.TANIKOD AND YIL_AY = m.cYil INTO ARRAY aTARA ORDER BY BIOPSINO


Aldığım yanıtlara göre indekslemeyi 5 field için de ayrı ayrı yapmak gerekiyor.

Yanılıyor muyum bilmiyorum.

Teşekkürler...

7

Re: SQL SELECT'de indeksleme nasıl olmalı?

Ben 5 tane sayamadim.
Where'de:
yerkodu, tanikodu, yil_ay geciyor sadece. Bir de distinct islemini kolaylastirmak icin biopsino (distinct yavas bir islem). SQLde distinct lafini hemen Select'den sonra yazmanda fayda var (daha dogrusu ben hic senin yazdigin gibi yazmadim, zarari var mi bilmiyorum).

select distinct biopsino ....

Diger taraftan bakinca senin tablon o kadar kucuk ki hepsini indexlesen de olur (hatta indexlemesen bile olur gibi:) Neredeyse milyonlarcasi bugunun makinelerinde RAM'a sigar. Bu arada hepsi karakter, buyuk/kucuk acisindan dikkat et. gerekiyorsa hepsini upper() ya da lower() ile indexle. VFP 'case sensitive'.

8

Re: SQL SELECT'de indeksleme nasıl olmalı?

DISTINT'i kullanmamın nedeni kimi zaman tarama sonucunda aynı biopsinolu kayıtlardan birden fazla çıkıyor. Örneğin yerkodu "uterus" ve tanı da "polip" ise hem endometriumda hem de servikste polibi olan olgu iki kez çıkıyor taramada, doğal olarak.
Aslında DISTINCT kullanmayıp elde ettiğim array'i bir for/next ile duplikasyonlar açısından temizlemeyi de seçebilirdim ama bu yöntem daha kolay geldi. Hız farkını sınamadım daha ama DISTINCT daha hızlı olabilir gibi geliyor bana.
Doğru; VFP'nin help'inde DISTINCT SELECT'ten hemen sonra yer alıyor. Ama ben yanlış yazmışım sanırım. Ama bu haliyle de ifade çalışıyor (hayret).
Toplam 22 çeşit tarama türü var. Ben önceki mesajımda en sık kullanılabilecek 2 tanesini verdim. Örneğin "yerleşim ne olursa olsun" tüm tümörleri bul dediğimde mg_kriter field'ı boş olmayanları vermesi gerekiyor. Çünkü tümörler 0, 1, 2, 3, 6 ve 9 gibi değerler alıyor. Tümör olmayan olguda ise bu field boş kalıyor.

SELECT BIOPSINO DISTINCT FROM YERTANI WHERE !EMPTY(MG_KRITER) AND ;
YIL_AY = m.cYil INTO ARRAY aTARA ORDER BY OTOPSINO

Aslında biopsino'ya göre indekslemek gereksiz görünüyor. Ancak ORDER BY BIOPSINO dediğim için gerekebilir sanırım.
Tüm field'larda sadece rakam kullanıyorum. Onun için case önemli değil.

Teşekkürler..

9

Re: SQL SELECT'de indeksleme nasıl olmalı?

Visual Fox Pro
WHERE !EMPTY(MG_KRITER) AND ;

YIL_AY = m.cYil

-YIL_AY indexin var, kisa devre kurali nedeniyle onu one al.
-Empty() optimize edilmiyor. Empty(MG_KRITER) diye bir index yaratmaya kalkarsan tipi binary olsun. Sonucu yalnizca True/False, 1/0 gibi olan seyler icin normal index anlamsiz ve yavaslatici.

Empty() optimize edilmiyor, anacak sen ayni deyimi:

Visual Fox Pro
!(MG_KRITER == '')

seklinde yazsaydin o da bos degilse anlaminda olacakti ve MG_KRITER indexini kullanacakti:)

10

Re: SQL SELECT'de indeksleme nasıl olmalı?

cetinbasoz yazdı:

...diye bir index yaratmaya kalkarsan tipi binary olsun. Sonucu yalnizca True/False, 1/0 gibi olan seyler icin normal index anlamsiz ve yavaslatici.
...


iyi ama ben vfp'nin helpini okudum. binary indeksleri for ile kullanamadığını söylüyor. bu indeksleri delete() kullanırsanız set delete on olunca rushmore bunları ayıklar diyor.

bu durumda delete() dışında nerde işe yarayacak bu indeksler? ben de bir çok yerde .t. veya .f. olan indeksler kullanıyorum sırf hız için. çok ta işime yarıyor...

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

11

Re: SQL SELECT'de indeksleme nasıl olmalı?

Metin,
For ile demedim. Sadece binary olarak yarat:

index on Kullanimda tag Kullanimda binary

binary olunca olusturdugu index bitmap index. Binary olmadigindaki problem sadece 2 deger oldugundan index tablosunda birisinden birisi bol miktarda, ya da 50-50. T'nin isine yaradiginda F'e yaramayabilir vs. Normal index oldugundan da boyu buyuk. Tek bir tabloda sadece bir logical yarat, indexle. Aynisini bir kopyede binary ile yap. Ikisine de bol miktarda rastgele data doldur ve bak:)

12

Re: SQL SELECT'de indeksleme nasıl olmalı?

Çetin Bey,
Kısa devre kuralı için teşekkürler.

Biliyorum filter sevmiyorsunuz ama; MG_KRITER'e göre indekslemede filter kullanmam
[!EMPTY(MG_KRITER) gibi] indeks dosyasını küçülteceği için daha iyi olmaz mı? Çünkü kayıtların ancak %35-40'ında MG_KRITER boş değil (yani çoğu olgu tümör değil)
Ayrıca bu, şöyle bir komutta sorun çıkarır mı?

SELECT DISTINCT BIOPSINO FROM YERTANI WHERE YIL_AY = m.cYil AND ;
!(MG_KRITER ==" ") INTO ARRAY aTARA ORDER BY OTOPSINO

Teşekkürler...