SQL bildirimde bulunuyor mu?


22

Soruyorum çünkü SQL'de gördüğüm soruların çoğu şu şekildedir: "Bu yavaş. Bunu nasıl hızlandırabilirim?"? Veya eğitmenler "Bunu bu şekilde yapın ve daha hızlı olduğu gibi yapmayın" olarak belirttiler.

Bana göre SQL’in büyük bir kısmı, bir ifadenin nasıl gerçekleştirileceğini ve bu bilgiden daha iyi performans gösteren ifade stillerini seçmeyi biliyor. Bu, bildirimsel programlamanın bir yönü ile karetmez - sistemin, hesaplamanın ne yapması gerektiğini sadece sizinle nasıl hesaplayacağına karar vermesine karar vermesidir.

Bir SQL motoru kullanıp kullanmadığınızı önemsememeli miydiniz in, existsyoksa joingerçekten bildirimsel ise, üç yöntemden biriyle mümkünse makul sürede doğru cevabı vermemeli mi? Bu son örnekte, açılış paragrafımda belirtilen türde olan bu son yazı isteniyor .

endeksleri

Sanırım kullanabileceğim en kolay örnek, bir tablo için indeks oluşturmakla ilgili. Gumph w3schools.com burada bile performans nedenleriyle olduğu kullanıcı tarafından görülmeyen bir şey olarak açıklamaya çalışır. Bunların açıklaması, SQL endekslerini deklaratif olmayan kampa koymuş gibi görünmektedir ve bunlar sadece performans nedenleriyle rutin olarak elle eklenmektedir.

Onların bir yerde olduğu, diğerlerinden çok daha açıklayıcı olan ancak kendilerinin duymadığı iyi bir SQL DB olduğu durumda mı?


@FrustratedWithFormsDesigner: Bunun ne anlama geldiğini tam olarak biliyorum. select whatever from sometable where FKValue in (select FKValue from sometable_2 where other_value = :param). Bunu bir existsveya a ile nasıl yeniden başlatacağınızı görmek önemsiz olmalıdır join.
Mason Wheeler

Benzer bir akıl yürütme kullanarak, normal ifadelerin "daha iyi performans elde etmek için bu şekilde yazmalısınız" tarafından verilen performans sorularını nadiren gördüğümden daha açıklayıcı bir ifade yöntemi olduğunu tahmin ediyorum. Beynimi sarıyorum ve cevabın regexp'i daha az sürede aynı şekilde farklı bir şekilde yeniden yazmak olduğu, yavaş bir regexp'te olumsuz geriye dönük veya ileriye dönük iddialarla ilgili bazı soruların yarısını hatırlayabiliyorum.
Paddy3118

Performans bir uygulama detayıdır. Sorgu işlemci geliştiricilerinin öncelikli olduğunu hissetmeleri durumunda, neredeyse her IN uygulamasının performansı EXISTS ve JOIN'den daha iyi veya karşılaştırılabilir olabilir.
JustinC

1
@JustinC, performans yönelimli SQL sorularının üstünlüğü ve sözde bildirimsel bir dil için ipuçları verilen bir ayrıntıdan daha fazlası gibi görünüyor?
Paddy3118

Bilgilendirici bir programlama dilinin açık bir tanımı yoktur ve bu nedenle konuşmanın anlamı yoktur. Bazı diller diğerlerinden daha üst seviyededir, hepsi bu.
gardenhead,

Yanıtlar:


21

SQL teorik olarak bildiricidir. Ama teori ile pratik arasındaki fark hakkında ne söylediklerini biliyorsun ...

Özünde, "bildirimsel programlama" kavramı hiç bu kadar etkili olmamıştı ve muhtemelen koda bakıp "bu kodun amacı nedir?" Sorusuna cevap verebilecek AI tabanlı bir derleyiciye sahip olana kadar asla olmayacak. Akıllıca, aynı şekilde onu yazan kişinin yazacağı gibi. Her bildirimsel dilin kalbinde, AI'nın yardımı olmadan bu sorunu çılgınca çözmeye çalışan bir dizi zorunlu kod vardır.

En yaygın durumlardır çünkü Genellikle, şaşırtıcı derecede iyi çalışıyor ortak vakalar dilin uygulanması yazanlar haberi ve sapa iyi yollar buldular. Fakat daha sonra uygulayıcının dikkate almadığı bir davaya karşı koşarsınız ve tercüman kodu tam anlamıyla daha fazla alıp daha az verimli bir şekilde ele almak zorunda kaldığından performansı hızlı bir şekilde düşürürsünüz.


3
Gerçekten etkili değil mi? SQL, LINQ, Knockout.js, Prolog, ELM dili. Tekrar kontrol etmek isteyebilirsiniz. Şu anda çoğunlukla bildirimsel teknolojiler kullanıyorum.
brian

5
@brian: Ve hiç kimse, hiç kimsenin düşünmediği son bir dava üzerine geldiğinde hızlıca yozlaşıyor. Sanırım " genel davada asla etkili olmadı" demeliydim .
Mason Wheeler

Cevabınız ne zaman bir SQL Server veritabanında saklandığını görme biçimini düşürecek şekilde ayarlandı? :) Nadiren, hiçbiri için çerçeve içinde çözülemeyen bir kenara çarptım. Nereden geldiğini anlıyorum ama son vakalar, bildirim kodunun% 99'unun ne kadar yararlı ve kolay olduğu konusunda bana çok fazla acı vermiyor. Clojure ya da F # 'nın kötü olduğunu söylemek gibi, çünkü probleminizi çözmek için değişken bir tip kullanmak zorunda kaldınız.
brian

11
@brian: I rarely hit an edge case in any of them that couldn't be solved within the framework.Evet, asıl mesele bu: çerçeve içinde çözmek için bir yol bulmak zorunda kalmak çünkü çerçeve sizin için başlangıçta ilan ettiğiniz şekilde çözmek için yeterince akıllı değil.
Mason Wheeler

Güncelleme için seçim ... ne olacak? Zorunlu bir komut gibi görünüyor.
Jesvin Jose

6

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_typemüş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

1
Birleşmeyi var olana yeniden yazma örneği ilginçtir. SQL geliştiricileri üzerinde etkilemeye çalıştığım kurallardan biri, DISTINCT kullanımının bir kod kokusudur - sorgu veya veri modeli çok yanlış olur ve farklı bir yaklaşım aranmalıdır.
David Aldridge,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.