baloglurecep yazdı: ↑12 Nis 2020 04:37
Bu sorguyu nasıl farklılaştırabilirim nasıl hızlandırabilirim?
Merhaba,
Yaklaşık ifadeler yanılmaya sebebiyet verebilir. IBExpert içinde sorgu çalıştırıldıktan sonra History kısmında çalışma süresini milisaniye cinsinden bulabilirsiniz. Uygulamanızda da kod ile süre tutup bu bilgiyi elde edebilirsiniz.
Standart IBExpert kurulumu sorgu sonuçlarının tamamını getirmez. Ekrana sığacak kayıt sayısı kadarını getirir (yaklaşık 25-30 adet) siz ekranada gözükmeyen kayıtları görmek için aşağı inmek istediğinizde kalan kayıtları almak için sunucu ile iletişim kurar. Bu noktada sizin sorgunuz yavaş çalıştığı için "donma" etkisi gösteriyor olabilir. Bunu önlemek için Options -> Environment Options içinde SQL Editor kısmında Fetch All isimli kutuyu işaretlemeniz gerekir.
FirebirdSQL tarafında yapabileceklerinizden bazıları;
(1) "musteriler.Id not In (SELECT satislar.musteri_Id FROM satislar WHERE (satislar.tur_id=2))" ifadesini aşağıdaki örneğe benzer LEFT JOIN kullanacak şekilde değiştirmeyi deneyin. Bu tür kullanım şekli FirebirdSQL optimize edicisinin kafasını karıştırabilir. Kullanabileceği indeks olsa bile kullanmıyor olabilir. Mesela bu ifadeyi hiç kullanmadığınızda performans artıyor ise sorununuzun kaynağı bu ifadede yatıyordur.
(2) WHERE kelimesinde kullanılan kolonlar için indeks oluşturun (MUSTERILER tablosu: "Gizle" kolonu, "Id" kolonu, SATISLAR tablosu: "tur_id" kolonu). Ancak genel anlamda çok fazla indeks oluşturmaktan da kaçının.
(3) Kullandığınız FirebirdSQL sunucu sürümüne uygun optimize edilmiş ayar dosyalarını kullanın:
https://ib-aid.com/en/optimized-firebird-configuration/
Yukarıdaki (1) numaralı öneri ile ilgili olarak:
Yaşadığınız yavaşlık sorununun bu madde olma ihtimali yüksek olduğuna inanıyorum. Bu anlamda LEFT JOIN kullanan örnek SQL:
Kod: Tümünü seç
SELECT
satislar.musteri_Id,
musteriler.adi_soyadi,
musteriler.adres,
musteriler.telefon,
musteriler.telefon1,
SUM(((musteriler.satis+musteriler.taksitlisatis) - (musteriler.odemeler - musteriler.odemeler_taksit))) AS BAKIYE
FROM
satislar
LEFT JOIN MUSTERILER on musteriler.id = satislar.musteri_Id
WHERE
musteriler.Gizle=0 AND satislar.tur_id=2
GROUP BY 1,2,3,4,5
Örnek SQL için çalıştırma planı:
Kod: Tümünü seç
Plan
PLAN SORT (JOIN (SATISLAR NATURAL, MUSTERILER NATURAL))
Sizin kullandığınız sorgu için çalıştırma planı:
Kod: Tümünü seç
Plan
PLAN (SATISLAR NATURAL)
PLAN (SATISLAR NATURAL)
PLAN (MUSTERILER NATURAL)
Göreceğiniz üzere sizin kullandığınız sorgu satışlar tablosunu iki kere baştan sona okuyor. Tavsiye olarak verilen SQL ise her iki tabloyu tek seferde okuyor. Dolu veritabanı olmadığı için her iki sorgu arasındaki performans farkını ve her iki sorgu aynı sonucu veriyor mu kontrol etmek mümkün olmadı.
NOT: Örnek planlar FirebirdSQL 3.0.4 ile hazırlanmıştır. Farklı sürümlerde farklı sonuçlar alınabilir.
NOT2: Plan için kullanılan tablo yapıları aşağıda verilmiştir.
Kod: Tümünü seç
/* HIC INDEKS OLUSTURULMADI */
CREATE TABLE MUSTERILER (
ID INTEGER,
ADI_SOYADI VARCHAR(80),
ADRES VARCHAR(200),
TELEFON VARCHAR(20),
TELEFON1 VARCHAR(20),
SATIS DECIMAL(18,4),
TAKSITLISATIS DECIMAL(18,4),
ODEMELER DECIMAL(18,4),
ODEMELER_TAKSIT DECIMAL(18,4),
GIZLE INTEGER
);
CREATE GENERATOR GEN_SATISLAR_ID;
/* SADECE AUTO INCREMENT KOLON ICIN INDEKS KULLANILDI */
CREATE TABLE SATISLAR (
AUTOINC INTEGER NOT NULL PRIMARY KEY,
MUSTERI_ID INTEGER,
TUR_ID INTEGER
);
SET TERM ^ ;
/* Trigger: SATISLAR_BI */
CREATE OR ALTER TRIGGER SATISLAR_BI FOR SATISLAR
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
IF (NEW.AUTOINC IS NULL) THEN
NEW.AUTOINC = GEN_ID(GEN_SATISLAR_ID,1);
END
^
SET TERM ; ^