
FireBird Ne Kadar Yeterli
-
- Kıdemli Üye
- Mesajlar: 1223
- Kayıt: 26 Nis 2005 04:08
20 milyon kayıtlı bir tablo firebird için çok mu?
Merhaba
İlk mesajda belirtilene benzer FireBird kullanan bir projeye başladım. Yeni başlık açma ihtiyacı duymadım bundan dolayı Firebird ile ilgili bir kaç soru sormak istiyorum. Yardımcı olacak arkadaşlara şimdiden teşekkürler.
Sayfalarca yer kaplayan metinleri database'e aktardım. Arama işlemlerinin hızlı bir şekilde yapılabilmesi içinde her bir metin içersindeki gereksiz kelimeleri ayırarak kalan kelimeleri indexledim. Index bilgilerinin saklandığı 2 tablo var "KELIME_KATALOGU" ve "METIN_KELIME_BAG".
"KELIME_KATALOGU" isimli tabloda 400 bin'e yakın kelime var. Bu tabloda arama yaptığımda sonuç çok kısa sürede geliyor. Bu tablo ile ilgili bir sıkıntım yok.
"METIN_KELIME_BAG" isimli tabloda ise Primary bir alan yok sadece METIN_ID ve KELIME_ID isimli index'lenmiş 2 integer alan var. Tablodaki kayıt sayısı ise 20 milyon dan biraz fazla.
Sorum şu; "METIN_KELIME_BAG" isimli tabloda aşağıdaki gibi bir arama yapınca sonuçlar en az 20 sn en fazla 2 dk içersinde geliyor. Bu süreler bana uzun geliyor. Gözden kaçırdığım bir durum mu var yoksa firebird burada yetersiz mi kalıyor?
İlk mesajda belirtilene benzer FireBird kullanan bir projeye başladım. Yeni başlık açma ihtiyacı duymadım bundan dolayı Firebird ile ilgili bir kaç soru sormak istiyorum. Yardımcı olacak arkadaşlara şimdiden teşekkürler.
Sayfalarca yer kaplayan metinleri database'e aktardım. Arama işlemlerinin hızlı bir şekilde yapılabilmesi içinde her bir metin içersindeki gereksiz kelimeleri ayırarak kalan kelimeleri indexledim. Index bilgilerinin saklandığı 2 tablo var "KELIME_KATALOGU" ve "METIN_KELIME_BAG".
"KELIME_KATALOGU" isimli tabloda 400 bin'e yakın kelime var. Bu tabloda arama yaptığımda sonuç çok kısa sürede geliyor. Bu tablo ile ilgili bir sıkıntım yok.
"METIN_KELIME_BAG" isimli tabloda ise Primary bir alan yok sadece METIN_ID ve KELIME_ID isimli index'lenmiş 2 integer alan var. Tablodaki kayıt sayısı ise 20 milyon dan biraz fazla.
Sorum şu; "METIN_KELIME_BAG" isimli tabloda aşağıdaki gibi bir arama yapınca sonuçlar en az 20 sn en fazla 2 dk içersinde geliyor. Bu süreler bana uzun geliyor. Gözden kaçırdığım bir durum mu var yoksa firebird burada yetersiz mi kalıyor?
Kod: Tümünü seç
SELECT METIN_ID FROM METIN_KELIME_BAG
WHERE KELIME_ID=5064 OR KELIME_ID=80060
Kod: Tümünü seç
CREATE TABLE KELIME_KATALOGU (
ID DOMAIN_INT NOT NULL /* DOMAIN_INT = INTEGER */,
KELIME DOMAIN_VC50 /* DOMAIN_VC50 = VARCHAR(50) */
);
CREATE TABLE METIN_KELIME_BAG (
KELIME_ID DOMAIN_INT /* DOMAIN_INT = INTEGER */,
KARAR_ID DOMAIN_INT /* DOMAIN_INT = INTEGER */,
KELIME_SAYISI DOMAIN_SMALL /* DOMAIN_SMALL = SMALLINT */
);
CREATE INDEX METIN_KELIME_BAG_IDX1 ON METIN_KELIME_BAG (KELIME_ID);
CREATE INDEX METIN_KELIME_BAG_IDX2 ON METIN_KELIME_BAG (METIN_ID);
Internet'te bir çok kaynakta MySql için yapılan testlerde müthiş hızlar elde edildiği belirtiliyor.
http://www.sphinxsearch.com/doc.html
Bu arada @celalatak sizin projenizin performansı nasıl?
http://www.sphinxsearch.com/doc.html
Bu arada @celalatak sizin projenizin performansı nasıl?
Aramayı nasıl yapıyorsunuz acaba?
Delphi'de yapıyorsanız, IB Expert gibi bir araçla aynı sorguyu çalıştırmayı denediz mi? Arada fark var mı? Mesela "ALİ" isimli kelimeyi delphi'de ve IB Expert'te listelemeniz ne kadar sürüyor.
Kayıt sayısı çok fazla ama sadece 2 tane alan var. Hızlı çalışır diye tahmin ediyorum.
Hız veritabanı seçiminde tek kriter değildir! Daha önce çok kez konuşulduğu için detaylarına pek girmiyorum.
Kolay gelsin.
Delphi'de yapıyorsanız, IB Expert gibi bir araçla aynı sorguyu çalıştırmayı denediz mi? Arada fark var mı? Mesela "ALİ" isimli kelimeyi delphi'de ve IB Expert'te listelemeniz ne kadar sürüyor.
Kayıt sayısı çok fazla ama sadece 2 tane alan var. Hızlı çalışır diye tahmin ediyorum.
Hız veritabanı seçiminde tek kriter değildir! Daha önce çok kez konuşulduğu için detaylarına pek girmiyorum.
Kolay gelsin.
Daha kodlama aşamasına geçmedim. Hala database tasarımını yapmaktayım. Bundan dolayı sorgulamaların tümünü IBExpert ile yapmaktayım.
"ALİ" Kelimesi "KELIME_KATALOGU" isimli tabloda yer alıyo. Bu tabloda bir birinden farklı 400 bin'e yakın kelime var ve bu tablodaki sorgular 1 sn den daha kısa sürede sonuçlanıyor. 20 milyonluk tabloda yaptığım sorgular çok uzun sürede sonuçlanıyor.
Tabiki bunun bilincindeyim. Diğer kriterleri yerine getirdiğimi düşünüyorum. Index oluşturma gibi mesala.mussimsek yazdı: Hız veritabanı seçiminde tek kriter değildir! Daha önce çok kez konuşulduğu için detaylarına pek girmiyorum.
"ALİ" Kelimesi "KELIME_KATALOGU" isimli tabloda yer alıyo. Bu tabloda bir birinden farklı 400 bin'e yakın kelime var ve bu tablodaki sorgular 1 sn den daha kısa sürede sonuçlanıyor. 20 milyonluk tabloda yaptığım sorgular çok uzun sürede sonuçlanıyor.
Merhaba
İlk mesajımda belirttiğim gibi sadece "METIN_KELIME_BAG" tablosunda arama yapıyordum. Memnun olmadığım performans aşağıda belirttiğim benzer sql cümlesi içindi.
Bellirttiğim tabloda 2 tane index vardı. 2 index'ide birleştirip tek bir index olarak tekrar yarattım ve metinleri tekrar katalogladım performans arttı. Sonuçlar şimdi 1,5 sn ile 5 sn arasında değişen süreler ile geliyor. Bu kabul edilebilir bir süre. Performans artışı yaptığım bu değişiklikten mi kaynaklanıyor anlayamadım. Belkide bilgisayarımın performansından kaynaklanıyordu.
Ama tabi ki bu sql cümlesini sadece deneme amaçlı kullandım. Asıl kullanmam gereken cümleyi aşağıda belirttim. Aşağıdaki sorgunun süresi ise tam 10 dk
. Etkin bir sql cümlesi oluşturamadım galiba.
Aşağıdaki sorgu ID'si 1, 6, 5 ve 439 olan kelimeleri aynı anda içeren (mantıksal "and" yani) metinleri veriyor. Yani belirtilen 4 adet metnin aynı anda bulunduğu kayıtları veriyor.
İlk mesajımda belirttiğim gibi sadece "METIN_KELIME_BAG" tablosunda arama yapıyordum. Memnun olmadığım performans aşağıda belirttiğim benzer sql cümlesi içindi.
Kod: Tümünü seç
SELECT METIN_ID FROM METIN_KELIME_BAG
WHERE KELIME_ID=5064 OR KELIME_ID=80060
Ama tabi ki bu sql cümlesini sadece deneme amaçlı kullandım. Asıl kullanmam gereken cümleyi aşağıda belirttim. Aşağıdaki sorgunun süresi ise tam 10 dk

Aşağıdaki sorgu ID'si 1, 6, 5 ve 439 olan kelimeleri aynı anda içeren (mantıksal "and" yani) metinleri veriyor. Yani belirtilen 4 adet metnin aynı anda bulunduğu kayıtları veriyor.
Kod: Tümünü seç
SELECT * FROM METIN WHERE ID IN
(SELECT METIN_ID FROM METIN_KELIME_BAG
WHERE KELIME_ID IN (1, 6, 5, 439)
GROUP BY METIN_ID
HAVING COUNT(METIN_ID)=4)
İlk performans artışı aslında 2 indeksi birleştirip tek index yapmaktan ziyade query'ide birleşen indeksin ilk alanını kullanmış olmandan kaynaklanmış gibi. Zira çok alanlı indekslerin ilk alanları sanki tek indeks gibi perfarmansı olumlu etkiliyor.
Burada bence ilk yapman gereken bütün tabloların için PRIMARY KEY tanımlaman. Bu tek INTEGER alan da olabilir veya tablo yapısına göre birden fazla alan da olabilir. Ben şahsen tek INTEGER alan tavsiye ederim. Zira diğer tanımlayacağın indekslerin performansını etkileyecektir.
Sonrasında da query'lerinde kullandığın tüm alanlar için tek tek INDEX tanımlaman. Ki başta bunu yapmışsın ama PRIMARY KEY tanımlamadığın için pek anlamı olmamış.
Bu yapıyı oluşturup test ettikten sonra artık gerisi yazdığın query'ileri optimize etmeye kalacaktır. Tahminim fazla bir gerek de kalmayacaktır.
İyi çalışmalar.
Burada bence ilk yapman gereken bütün tabloların için PRIMARY KEY tanımlaman. Bu tek INTEGER alan da olabilir veya tablo yapısına göre birden fazla alan da olabilir. Ben şahsen tek INTEGER alan tavsiye ederim. Zira diğer tanımlayacağın indekslerin performansını etkileyecektir.
Sonrasında da query'lerinde kullandığın tüm alanlar için tek tek INDEX tanımlaman. Ki başta bunu yapmışsın ama PRIMARY KEY tanımlamadığın için pek anlamı olmamış.
Bu yapıyı oluşturup test ettikten sonra artık gerisi yazdığın query'ileri optimize etmeye kalacaktır. Tahminim fazla bir gerek de kalmayacaktır.
İyi çalışmalar.
Merhaba
Hakan bey Primary Key barındırmayan tek tablo yukarıdada belirttiğim gibi içersinde 20 milyon kayıt olan "METIN_KELIME_BAG" isimli tablodur. Aşağıda tablonun yapısını belirttim. Görüldüğü gibi arama yaptığım alanlar için hem UNIQUE alan hemde INDEX alan oluşturdum. Bunlar yeterli diye düşünmekteyim. Ama yinede "ID" isminde Primary Key bi alan tanımlayıp tekrar denicem.
phpBB3'ün kodlarını indirip onlar bu işi nasıl yapmış diye bi baktım. Onların database yapısı tasarladığım database yapısı ile aynı. Yani Mesajların saklandığı, kelimelerin saklandığı ve bağlantı bilgilerinin saklandığı tablolar var. Benimkilerin Türkçe olması dışında alan isimleri bile aynı
.
Yine phpBB3'ün kodlarını inceledim ve arama işini Self Join bir yapı ile halletmişler. Bende hemen aşağıdaki sql kodunu yazdım. Bu sefer arama süresi en az 1,5 dk sürüyor. Eh 10dk olmasından iyi dir ama 1,5dk arama süresi olan bi prg'yi kimse kullanmak istemez herhalde.
Hakan bey Primary Key barındırmayan tek tablo yukarıdada belirttiğim gibi içersinde 20 milyon kayıt olan "METIN_KELIME_BAG" isimli tablodur. Aşağıda tablonun yapısını belirttim. Görüldüğü gibi arama yaptığım alanlar için hem UNIQUE alan hemde INDEX alan oluşturdum. Bunlar yeterli diye düşünmekteyim. Ama yinede "ID" isminde Primary Key bi alan tanımlayıp tekrar denicem.
Kod: Tümünü seç
CREATE TABLE KARAR_KELIME_BAG (
KELIME_ID DOMAIN_INT /* DOMAIN_INT = INTEGER */,
KARAR_ID DOMAIN_INT /* DOMAIN_INT = INTEGER */,
KELIME_SAYISI DOMAIN_SMALL /* DOMAIN_SMALL = SMALLINT */
);
ALTER TABLE KARAR_KELIME_BAG ADD CONSTRAINT UNQ1_KARAR_KELIME_BAG UNIQUE (KELIME_ID, KARAR_ID);
CREATE INDEX KARAR_KELIME_BAG_IDX1 ON KARAR_KELIME_BAG (KELIME_ID);
CREATE INDEX KARAR_KELIME_BAG_IDX2 ON KARAR_KELIME_BAG (KARAR_ID);

Yine phpBB3'ün kodlarını inceledim ve arama işini Self Join bir yapı ile halletmişler. Bende hemen aşağıdaki sql kodunu yazdım. Bu sefer arama süresi en az 1,5 dk sürüyor. Eh 10dk olmasından iyi dir ama 1,5dk arama süresi olan bi prg'yi kimse kullanmak istemez herhalde.
Kod: Tümünü seç
SELECT M.ID, M.TARIH
FROM
METIN M,
METIN_KELIME_BAG M0,
METIN_KELIME_BAG M1,
METIN_KELIME_BAG M2
WHERE
(M0.METIN_ID = M.ID) AND
(M0.METIN_ID = 1) AND
(M1.METIN_ID = 16) AND
(M2.METIN_ID = 485) AND
M1.METIN_ID = M0.METIN_ID AND
M2.METIN_ID = M0.METIN_ID
Bu arada Amd Athlon 2800+ işlemci 1GB ram var sistemde. Database'in Page Size'ı ise 16384, Database dosya boyutu 2,2 GB ve "firebird.conf "dosyasında sadece "DefaultDbCachePages" ayarı "4096" yapıldı. Onun dışında FB default ayarları ile kuruldu.
Metinler metin tablosunda saklanıyor ve 65.000 tane indexlenmiş metin var. Sayfalarca yer kaplayan bu blob alanlarda arama yapmak 30 sn sürüyor. Yani kendi oluşturduğum Manual Full-Text search tablolarında arama yapmaktan bile daha kısa sürüyor.
Bu sorgu 30 sn sürüyor. Sayfalarca yer tutan 65.000 adet belge için gayet iyi bi süre.
Metinler metin tablosunda saklanıyor ve 65.000 tane indexlenmiş metin var. Sayfalarca yer kaplayan bu blob alanlarda arama yapmak 30 sn sürüyor. Yani kendi oluşturduğum Manual Full-Text search tablolarında arama yapmaktan bile daha kısa sürüyor.
Kod: Tümünü seç
SELECT ID, TARIH FROM METIN WHERE ICERIK CONTAINING '%DENEME%'
20 milyonluk tabloya Primary Key tanımlayıp tekrar denedim ama değişen bir şey olmadı.Hakan Can yazdı: Burada bence ilk yapman gereken bütün tabloların için PRIMARY KEY tanımlaman. Bu tek INTEGER alan da olabilir veya tablo yapısına göre birden fazla alan da olabilir. Ben şahsen tek INTEGER alan tavsiye ederim. Zira diğer tanımlayacağın indekslerin performansını etkileyecektir.
Firebird benim için önemli. FB'den asla vazgeçemem. Ancak bu projede hız önemli. Bu yüzden başka veritabanları ile denemeler yapmak istiyorum. Benzer bir tecrübesi olupda ücretsiz başka bir VT tavsiye edecek arkadaşlar var mı acaba.
SQLite'ı denemek istiyorum ancak resmi olarak server/client desteği yok. Bu iş için bazı eklentiler yapılmış ama piyasada kullanılması (müşteride) zor görünüyo.
İster 10 dakika ister 30 saniye sürsün, sıradan kullanıcıların sabrı 3 saniyeyi nadiren geçecektir.
Yazılımcının hedefi mümkün mertebe bu süreyi 1 saniyenin altında tutmak olması gerekiyor.
İstersen 24 saat süren bir sorgulamayı 10 saniyeye indir. Onlar için pek anlamı yok.
Gerçi haklılar da bir noktada.
Sonuçta GOOGLE'da çok daha kompleks aramalar 1 saniyenin çok altında sürüyor.
Bu arada 20 milyon kayıt çok fazla. Ben şahsen başta okurken 2 milyon diye algılamışım.
MS SQL Server'da bu tip queryler başta FIREBIRD kadar sürerken sonraki sorgulamalar çok hızlı sonuç döndürüyor. Nedeni de ilk sorguda tabloyu hafızaya alması ve sonrasında hafızada yapması sorgulamaları.
Ama sonuçta bu da bir çözüm olmayacaktır. Zira MS SQL Server'ı her bilgisayar kaldırmayabilecektir.
Bu noktada 20 milyon kayıtlı tablonun yapısını değiştirmeyi deneyebilirsin.
Ya alan sayısını çok daha arttırabilirsin. Ki bu proje için pek uygun gözükmüyor.
Ya da bu tabloyu kelimelerin ilk karakterlerine veya hatta bazı kelimeler muhakkak çok daha fazladır buna göre ilk iki karakterlerine göre mesela 100-200 tane tabloya bölerek tabloların kayıt sayısını 100 bin civarında tutmak. Ve queryleri de gerekirse 3-5 tabloda yapmak.
100 bin kayıtlı benzer bir tabloda bir query herhalde en fazla 0.1-0.2 saniye falan sürecektir.
Tabi bu yapıda Delphi tarafında biraz fazla kod yazman gerekecek.
Hem bu yapıda diyelim ki 5 tane ayrı tablo için ayrı ayrı query çalıştırman gerekecek. Olaki ilk query veya sonuncudan öncekilerden herhangi biri olumsuz sonuç döndürdü, bu durumda diğerlerini de çalıştırmana gerek kalmayacaktır.
En azından 1 tane 100 bin kayıtlı aynı yapıda bir tablo oluşturup query hızını test edebilirsin.
Hatta tablo sayısını çok daha arttırıp kayıt sayısını çok daha düşürmek daha uygun olacaktır.
Kolay gelsin.
Yazılımcının hedefi mümkün mertebe bu süreyi 1 saniyenin altında tutmak olması gerekiyor.
İstersen 24 saat süren bir sorgulamayı 10 saniyeye indir. Onlar için pek anlamı yok.
Gerçi haklılar da bir noktada.
Sonuçta GOOGLE'da çok daha kompleks aramalar 1 saniyenin çok altında sürüyor.
Bu arada 20 milyon kayıt çok fazla. Ben şahsen başta okurken 2 milyon diye algılamışım.
MS SQL Server'da bu tip queryler başta FIREBIRD kadar sürerken sonraki sorgulamalar çok hızlı sonuç döndürüyor. Nedeni de ilk sorguda tabloyu hafızaya alması ve sonrasında hafızada yapması sorgulamaları.
Ama sonuçta bu da bir çözüm olmayacaktır. Zira MS SQL Server'ı her bilgisayar kaldırmayabilecektir.
Bu noktada 20 milyon kayıtlı tablonun yapısını değiştirmeyi deneyebilirsin.
Ya alan sayısını çok daha arttırabilirsin. Ki bu proje için pek uygun gözükmüyor.
Ya da bu tabloyu kelimelerin ilk karakterlerine veya hatta bazı kelimeler muhakkak çok daha fazladır buna göre ilk iki karakterlerine göre mesela 100-200 tane tabloya bölerek tabloların kayıt sayısını 100 bin civarında tutmak. Ve queryleri de gerekirse 3-5 tabloda yapmak.
100 bin kayıtlı benzer bir tabloda bir query herhalde en fazla 0.1-0.2 saniye falan sürecektir.
Tabi bu yapıda Delphi tarafında biraz fazla kod yazman gerekecek.
Hem bu yapıda diyelim ki 5 tane ayrı tablo için ayrı ayrı query çalıştırman gerekecek. Olaki ilk query veya sonuncudan öncekilerden herhangi biri olumsuz sonuç döndürdü, bu durumda diğerlerini de çalıştırmana gerek kalmayacaktır.
En azından 1 tane 100 bin kayıtlı aynı yapıda bir tablo oluşturup query hızını test edebilirsin.
Hatta tablo sayısını çok daha arttırıp kayıt sayısını çok daha düşürmek daha uygun olacaktır.
Kolay gelsin.
20 milyon kayıtlı tablom hiç olmadığından bir şey diyemem. Fakat oluşabilecek yapıya uygun bir pagesize, diğer parametreler ve indeksleme ile çözülebilir diye düşünüyorum. Burada text search ile ilgili bazı bilgiler var.
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!