UPDATE de FIRST komutu kullanımında hız problemi.

Firebird ve Interbase veritabanları ve SQL komutlarıyla ilgli sorularınızı sorabilirsiniz. Delphi tarafındaki sorularınızı lütfen Programlama forumunda sorunuz.
Cevapla
sen
Üye
Mesajlar: 34
Kayıt: 04 Tem 2003 12:33
Konum: Ankara

UPDATE de FIRST komutu kullanımında hız problemi.

Mesaj gönderen sen » 08 Oca 2008 06:42

SA.
herkese iyi çalışmalar.
Firebirt 2.0
SQL ile, ilk 10 kayıtta değişiklik yapmak istiyorum.
ilk aklıma gelen;

Kod: Tümünü seç

UPDATE VERILER SET ACIKLAMA='İlk on kayıt'
WHERE 
 KAYIT_NO IN 
(SELECT FIRST 10 KAYIT_NO FROM VERILER WHERE ALAN1='A' ORDER BY KAYIT_NO)
yaklaşık 1.200 adet kayıtta bu işlem yaklaşık 90 saniye sürdü.
Ama FIRST 10 komutunu kaldırınca 3 saniye bile sürmüyür.

Kod: Tümünü seç

UPDATE VERILER SET ACIKLAMA='İlk on kayıt'
WHERE 
 KAYIT_NO IN 
(SELECT KAYIT_NO FROM VERILER WHERE ALAN1='A' ORDER BY KAYIT_NO)
1. Bu yavaşlığın sebebi ne olabilir.
2. UPDATE işlemi için ilk 10 kayıtta değişiklik yapmanın başka yolları neler olabilir. Bunu SQL ile yapmam lazım. kayıt_no sırası da önemli.

herkese iyi günler...

Kullanıcı avatarı
Ali Erdoğan
Kıdemli Üye
Mesajlar: 1026
Kayıt: 11 Şub 2005 02:12
Konum: İstanbul

Mesaj gönderen Ali Erdoğan » 08 Oca 2008 10:04

Yavaşlığın sebebi bir bug olabilir. KAYIT_NO alanı birincil anahtar mı? Eğer öyle değilse bu alan için bir index oluşturup tekrar deneyebilir misin?

ikutluay
Üye
Mesajlar: 2341
Kayıt: 03 Tem 2007 09:13

Mesaj gönderen ikutluay » 09 Oca 2008 09:13

içiçe select tarzı ifadeler yapıları gereği yavaş çalışırlar o ayrı ama banada index sorunu olması muhtemel gibi görüntü. çünkü neye göre ilk 10. alanda index yoksa , geçici index oluştur, sırala derken iş tıkanmış olabilir.
Kişi odur ki, koyar dünyada bir eser. Eseri olmayanın yerinde yeller eser./Muhammed Hadimi
http://www.ibrahimkutluay.net
http://www.ibrahimkutluay.net/blog

Hakan Can
Üye
Mesajlar: 634
Kayıt: 04 Mar 2005 04:27
Konum: Ankara

Mesaj gönderen Hakan Can » 09 Oca 2008 09:47

FireBird'ün çalışma mantığı bizim düşündüğümüzden farklı.

FireBird kayıt bazlı çalışıyor.

Daha net söylemek gerekirse bu UPDATE komutunda 1200 kayıdın herbirinde WHERE şartındaki SELECT komutunu tekrar çalıştırıyor.

Zira bir kayıt UPDATE olduğunda WHERE şartındaki SELECT komutu UPDATE edilen aynı TABLO olduğu için olaki şart ve sonuç değişmiştir gibi düşünüyor.

FireBird'ün çalışma şekli ile ilgili özetle bu olay.

Farklı çözümler geliştirmek gerekir.

Normalde değil 1200 kayıt, 1 milyon kaydın UPDATE işlemi bu kadar sürmez.

İyi çalışmalar.

Kullanıcı avatarı
Kuri_YJ
Moderator
Mesajlar: 2247
Kayıt: 06 Ağu 2003 11:07
Konum: İstanbul
İletişim:

Mesaj gönderen Kuri_YJ » 11 Oca 2008 08:42

Selamlar,

KayitNo alanı için bir index tanımlayın, ayrıca Alan1 için de bir index tanımlayın. Sonra tekrar deneyin. Bakalım hız değişecek mi?

Kolay Gelsin
Kuri Yalnız Jedi
Harbi Özgürlük İçin Pisi http://www.pisilinux.org/

sen
Üye
Mesajlar: 34
Kayıt: 04 Tem 2003 12:33
Konum: Ankara

Mesaj gönderen sen » 11 Oca 2008 10:52

öncelikle ilginiz için teşekkürler..

KAYIT_NO birincil indeks, ve ALAN1 de indeksli.

ve dahası mesela FIRST 5 , FIRST 1200 den daha yavaş çalışıyor.

mesele, hakan can beyin yazdığı mantık olabilir.

iyi çalışmalar...

Kullanıcı avatarı
Kuri_YJ
Moderator
Mesajlar: 2247
Kayıt: 06 Ağu 2003 11:07
Konum: İstanbul
İletişim:

Mesaj gönderen Kuri_YJ » 11 Oca 2008 11:33

Selamlar şöyle bir mantık uygulayarak deneseniz,

Kod: Tümünü seç

UPDATE titles
        SET t.ytd_sales = t.ytd_sales + s.qty
FROM titles t, sales s
WHERE t.title_id = s.title_id
AND s.ord_date = (SELECT MAX(sales.ord_date) FROM sales)

Yada yapacağınız UPDATE'i iki adımda tamamlayın,

1. Adım SELECT FIRST 10 Kayıt ve bu kayıtları Temp bir tabloya alın
2. Adımda ise UPDATE'inizi VERILER tablosunu kullanarak değil onun yerine TEMP tablonuzu kullanarak ve IN şeklinde değil doğrudan ='lik şeklinde yapabilirsiniz.

Kod: Tümünü seç


SELECT FISRT 10 *
FROM VERILER 
INTO TEMP_TABLE
WHERE ALAN1 = 'A'
ORDER BY KAYIT_NO


UPDATE VERILER
SET ACIKLAMA = 'İlk on kayıt'
FROM TEMP_TABLE
WHERE VERILER.KAYIT_NO = TEMP_TABLE.KAYIT_NO

Yukarıdaki kod doğru olmayabilir, siz FB'ye göre düzenleyebilrisiniz sanırım :) Mantık oluşturması için hemen aklıma geleni yazdım.

Kolay Gelsin
Kuri Yalnız Jedi
Harbi Özgürlük İçin Pisi http://www.pisilinux.org/

Kullanıcı avatarı
Kuri_YJ
Moderator
Mesajlar: 2247
Kayıt: 06 Ağu 2003 11:07
Konum: İstanbul
İletişim:

Mesaj gönderen Kuri_YJ » 11 Oca 2008 11:36

Tekrar Selamlar,

Aklıma başka bir şey daha geldi. 2 Alanlı bir index tanımlayın.

Bu index ALAN1 ve KAYIT_NO şeklinde ve sırasında olsun. Bir de öyle deneyin.

Aslında FIRST komutu mecburen Tabloyu sonuna kadar tarar (eğer doğru index yok ise) Ki Siz burada ALAN1'den filtreleme yapıp, ardından KAYIT_NO alanına göre ORder edilmiş bir biçimde kullanıyorsunuz.

Ayrıca, VERILER tablosundaki tüm kayıtları Ana UPDATE sorgusunda dolaştırtıyorsunuz. Her kayıt için SELECT FIRST çekmek zorunda kalıyor anladığım kadarı ile. Bu sebeple de kastırıyor olabilir. Aklıma gelen nedenler bunlar.

Kolay Gelsin
Kuri Yalnız Jedi
Harbi Özgürlük İçin Pisi http://www.pisilinux.org/

aLonE CoDeR
Kıdemli Üye
Mesajlar: 1223
Kayıt: 26 Nis 2005 03:08

Mesaj gönderen aLonE CoDeR » 11 Oca 2008 11:43

Selamlar.

@HakanCan'ın değindiği konu sebebiyle bu yavaşlık göze çarpıyor. Burada veritabanından kaynaklanan bir yavaşlık değil de sorgu yapısından kaynaklı bir durum sözkonusu. Öncelikle bu yapıyı değiştirmenin yoluna gitme şansın var mı bunu irdelemek gerek. Eğer mümkünse SubSQL kullanmadan bir çözüm üretilmeli ama yok mecburiyse SubSQL için bir view oluşturarak oradan select edilmeli.

Kolay gele.

serkan
Üye
Mesajlar: 666
Kayıt: 09 Tem 2003 11:08
Konum: bursa

Mesaj gönderen serkan » 13 Oca 2008 06:53

firs 15 kaydı listeliyip döngüyle açıklama alanlarını değiştirsen daha hızlı olur.madem 90 sn.sürüyor.

Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4481
Kayıt: 10 Haz 2003 12:48
Konum: İstanbul

Mesaj gönderen rsimsek » 20 Oca 2008 12:02

@HasanCan ın tespiti genel veri tabanı mantığı içerisinde bakınca doğru olmasa da FB için doğru olabilir. Genel veri tabanı derken aynı tablo üzerinde yapacağınız değişiklik (UPDATE) sonsuz/kısır bir döngüye girmesine sebep olabilir. Dolaysıyla böyle durumlara mantiken iç transaction lar şeklinde (snapshut) düşünülerek içteki SELECT işleme başlanmadan önceki durum esas alınır. Belki yukarıdaki çözüm önerilerine ek olarak tek satırda yapmaktansa ayrı bir view den farklı bir tabloymuş gibi KAYIT_NO lar çekilebilir. Ya da kod içinden önce bir sorgu ile KAYIT_NO lar alınıp UPDATE Where ine string olarak eklenebilir :idea:
@Kuri_YJ de benzer bir çözüm önermiş.
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!

Cevapla