1 Mart 2014 Cumartesi

Delphi XE5 - ClientDataSet İşlemlerde(SUM,AVG) Hız İçin ARRAY 'lerle Çalışma


   ClientDataSet 'te daha önce sütundaki değerlerin toplamını ,ortalamasını yada standart sapmasını nasıl aldırabileceğini yazmıştım. Ama bu işlemi yaparken veritabanı for döngüsüyle her işlem için ayrı ayrı döndürülmek zorundaydı. Bu yöntem kullanılabilir fakat küçük veritabanlarında. Çünkü bu işlemi yaparken ana ekrandaki tabloda işlemin hareketini görebiliyor bu da yapılan işlemin uzun süremesine neden oluyor. Navigatör eklerseniz birde düşünün uzayacak zamanı.



  Peki bu işlemi yaparken hem ana ekranda işlemin yapılışını görmeyecek hemde işlemi nasıl yapabiliriz. Bu işlemi Arrayler yani dizi işlemleri ile çok rahat yapabiliriz. Peki nasıl? Veri oluştuğu anda bu veriyi eğer oluşturacağımız bir Arrayin içine atarsak daha sonra normalde ekranda görmediğimiz bu Arrayi başka bir işlem için tekrar çağırabiliriz.

 Bunu yaparken veri üretme uygulamasından yararlanacağım yine. Uygulamada yaş sütunu bulunmak ta eğer ki bu sütunu for döngüsüyle toplamaya kalkarsam bu işlem çok büyük veri kümelerinde inanılmaz bir yavaşlığa neden olacaktır. Veriler dönerken bizde DBGrid den takip edebildiğimiz den işlem süresi uzayacaktır. Ama Arrayin içine kaydettiğimiz veriyi toplamaya kalkarsak inanılmaz bir hızda işlem gerçekleşecektir.

Uygulamanın arayüzü :

  Şimdi gelelim kodlamaya. Bu veriyi bu Arrayin içine nasıl kaydedeceğiz. Daha önceki uygulamalara baktıysanız veri üretmek içinde yine Arrayleri kullanmış ve ad,soyad için bir havuz oluşturmuş bunları Arraylerin içinden çekmiştim. Bu sefer tam tersini yapacak ve içine yazdıracağım.

  Array yapısından genel olarak yazarsak:

ismi : uzunluğu=[....] of verinintipi

  Benim Array 'ime veribank ismini vedim ve bir milyon uzunluğunda olacak. Veri tipide extended. Bu dediklerimi yazacak olursak.

veribank: array[1..1000000] of extended;

  Artık verilerimi bu oluşturduğum Arrayim içine aktarabilirim. Bunun için incelikle daha önceki uygulama yazsındaki veriyi üret fonksiyonunun içine girmek lazım. Veri üretildiği anda bir Arrayin içine aktarmalıyım. Uygulamanın üret fonksiyonu:

function üret(clientdataset:tclientdataset; nekadar:tedit; durum:TProgressBar; sure:tlabel ) :boolean;
var
 i , rnd1, rnd2 : integer;
 start,stop : tdatetime;
 sonuc :string;

begin
   start := (now);
   durum.Position := 0;
   durum.Min := 0;
   durum.Max := StrToInt(nekadar.Text);
  for i := (clientdataset.RecordCount+1) to (clientdataset.RecordCount+strtoint(nekadar.Text)) do
  begin
//--------------------------------------------------------
    rnd1 := RandomRange(1,16);
    rnd2 := RandomRange(1,16);
     clientdataset.insert;
     clientdataset.FieldByName('id').Value := i;
     clientdataset.FieldByName('age').Value := RandomRange(13,65);
     veribank[i] := ClientDataSet.FieldByName('age').Value;
     clientdataset.FieldByName('name').Value := isim[rnd1];
     clientdataset.FieldByName('surname').Value := soyisim[rnd2];
     durum.Position := i;
     durum.Update;

     clientdataset.Next;
//---------------------------------------------------------
   end;
   stop := now - start;
   sonuc := formatdatetime('hh.nn.ss',stop);
   sure.caption :='Süre: ' +sonuc   ;
end;

 Görüldüğü gibi yaş verisi ürettiğim gibi bir Arrayin içine alıyorum. Şimdi bu Arrayi toplama, ortalama alma ve standart sapma hesaplamada kullanalım:

Hesapla butonuna tıklıyoruz ve yine daha önce kullandığımız toplama fonksiyonu mantığını izleyeceğiz. Ama bu sefer ClientDataSet değil Arrayi kullanacağız. Bunları daha önce anlattığım için çok fazla üstünde durmayacağım yaptığım. Olay içine veri kaydedilmiş Arrayi tekrar çağırarak aslında bizim görmediğimiz ama tonlarca veriyi saniyeler içinde hesaplatabilmek. Kodlara bakacak olursanız :

procedure TForm4.Button3Click(Sender: TObject);
var
 i,n : integer;
 toplam,ort,varyans,stdev :extended;
begin
toplam := 0;
n := 0;
  for I := 1 to ClientDataSet1.RecordCount do
 begin
  toplam := toplam + veribank[i];
  n := n + 1;
 end;
  ort := toplam / n;

   if RadioButton1.Checked = true then label4.Caption := FloatToStr(toplam)
  else  if RadioButton2.Checked = true then label4.caption := FloatToStr(ort);

n := 0;
toplam := 0;
 for i := 1 to ClientDataSet1.RecordCount do
  begin
    toplam := toplam + ((veribank[i]-ort)*(veribank[i]-ort));
    n := n + 1;
  end;
 varyans := toplam / n-1;
 stdev := sqrt(varyans);

  if RadioButton4.Checked = true then label4.Caption := floattostr(varyans)
  else  if RadioButton3.Checked = true then  label4.Caption := FloatToStr(stdev);

end;

  Artık Arraylere veri aktarmayı öğrendiniz. Başka sayısal verilerinizi bu şekilde Arraylere atarak çok daha hızlı işlemler döndürebilirsiniz. Ürettiğim üç yüz bin veriyi saliseler içinde toplatıp ortalamasını alabiliyorum. Denemek için örnek uygulamayı aşağıdan indirin.


  Verileri üret fonksiyonunun dışında form oluşurken Arrayin içine almak istiyorsak ta şöyle bir fonksiyon kullanabilirsiniz.

function acılısverisi(clientdataset:TClientDataSet):boolean;
 var i :integer;
 begin
 ClientDataSet.First;
  for i := 1 to ClientDataSet.RecordCount do
  begin
    veribank[i] := ClientDataSet.FieldByName('age').Value;
    clientdataset.Next;
  end;
 end;

Kullanımı:

procedure TForm4.FormCreate(Sender: TObject);
begin
acılısverisi(ClientDataSet1);
end;

 Böylece başlangıçtada eski verileri kullanabiliriz.

Okuduğunuz İçin Teşekkür Ederim
Hakan UÇAR
İstatistikçi ve Amatör Programcı
İçerikler Tamamen Ücretsiz Olup Özgün Anlatımdır Paylaşırken Kaynak Belirtiniz Lütfen.

Uygulamayı Yandex Diskimden indirebilirsiniz.

Yandex Disk Benim Linkimle Her Üye olana 1 GB Size 0,5 GB Bana Extra Alan Vermekte Aşağdıdaki Resmi Tıklayıp Üye Olursanız Sevinirim.

                                              Bumerang - Yazarkafe

0 yorum:

Yorum Gönder