Bunu birkaç gün önce bir SQL optimizasyonundan sonra düşünüyordum. SQL’in Wikipedia’nın tanımında “beyan edici bir dil” olduğu konusunda hemfikir olduğumuzu düşünüyorum:
Kontrol akışını açıklamadan hesaplama mantığını ifade eden programlama paradigması
Perdelerin arkasında kaç şey yapıldığını düşünüyorsanız (istatistiklere bakmak, bir endeksin yararlı olup olmadığına karar vermek, iç içe geçmiş, birleştirilmiş veya karma birliğe katılmak, vb.). mantık ve veritabanı tüm düşük seviye kontrol akış mantığına dikkat etti.
Ayrıca bu senaryoda, bazen veritabanı en iyi duruma getiricisinin en iyi sonuçları vermesi için kullanıcıdan bazı "ipuçları" alması gerekir.
"Bilgilendirici" dilin diğer bir yaygın tanımı: (Yetkili bir kaynak bulamıyorum):
İstenen hesaplama sonucunu, elde etme adımlarını tanımlamaksızın ifade eden programlama paradigması (ayrıca "nasıl olduğunu değil, nasıl yapılacağını" ile kısaltılır)
Bu tanımı kabul edersek, OP tarafından açıklanan sorunlarla karşılaşırız.
İlk sorun, SQL'in "aynı sonucu" tanımlamak için bize birden çok eşdeğer yol vermesidir. Muhtemelen bu gerekli bir kötülük: bir dile ne kadar ifade gücü verirsek, aynı şeyi ifade etmenin farklı yolları olabilir.
Örnek olarak, bir kez bu sorguyu optimize etmem istendi:
SELECT Distinct CT.cust_type, ct.cust_type_description
from customer c
INNER JOIN
Customer_type CT on c.cust_type=ct.cust_type;
Türler müşteriden çok daha az olduğundan ve cust_type
müşteri masasında bir endeks olduğundan, aşağıdaki gibi yeniden yazarak büyük bir gelişme sağladım:
SELECT CT.cust_type, ct.cust_type_description
from Customer_type CT
Where exists ( select 1 from customer c
Where c.cust_type=ct.cust_type);
Bu özel durumda, geliştiriciye ne elde etmek istediğini sorduğumda bana "En az bir müşterim olan tüm müşteri türlerini istedim" demişti; bu, bu arada, optimizer sorgusunun tam olarak nasıl tanımlanabileceğini söyledi.
Öyleyse, eşdeğer ve daha verimli bir sorgu bulabilirsem, neden optimize edici aynı şeyi yapamıyor?
En iyi tahminim iki ana sebepten kaynaklandığıdır:
SQL mantığı ifade eder:
SQL yüksek seviyeli bir mantık ifade ettiğinden, optimize edicinin bizi ve mantığımızı "zekâsı" olmasını ister miydik? Optimize ediciyi en verimli uygulama yolunu seçmeye zorlamak zorunda kalmam her zaman olmasaydı, heyecanla "evet" diye bağırırdım. Bu fikrin, optimize edicinin elinden gelenin en iyisini yapmasına izin vermek (mantığımızı da gözden geçirmek için) sağlamak, ancak bir şey çıldırdığında (tekerlek + frenler içinde olmak gibi olur) bize bir "ipucu mekanizması" vermek olduğunu düşünüyorum. özerk bir araba).
Daha fazla seçenek = daha fazla zaman
En iyi RDBMS iyileştiricisi bile, TÜM olası yürütme yollarını test etmiyor, çünkü gerçekten hızlı olması gerekiyor: 100ms'den 10ms'ye bir sorguyu optimize etmek, her zaman 100ms'yi en iyi yolu seçerek harcamam gerekirse ne kadar iyi olurdu? Ve bu, "üst düzey mantığımıza" saygı duyan eniyileyici ile birlikte. Tüm eşdeğer SQL sorgularını da test etmesi gerekiyorsa, optimizer süresi birden çok kez artabilir.
Sorguların bir başka iyi örneği, RDBMS'nin aslında yapabilecek kabiliyetini yazmadığını yeniden yazmaktır ( bu ilginç blog gönderisinden )
SELECT t1.id, t1.value, SUM(t2.value)
FROM mytable t1
JOIN mytable t2
ON t2.id <= t1.id
GROUP BY t1.id, t1.value;
bunun gibi yazılabilir (Analitik fonksiyonlar gereklidir)
SELECT id, value, SUM(t1.value) OVER (ORDER BY id)
FROM mytable
select whatever from sometable where FKValue in (select FKValue from sometable_2 where other_value = :param)
. Bunu birexists
veya a ile nasıl yeniden başlatacağınızı görmek önemsiz olmalıdırjoin
.