2012-10-13 27 views
5

Aynı sorguda aynı toplama işlevine birden çok çağrı için SQL implementatonunda standart var mı?SQL toplama fonksiyonu hesaplaması için bir standart var mı?

Örneğin, popüler bir örnek şema dayalı aşağıdaki örneği ele alalım:

SELECT Customer,SUM(OrderPrice) FROM Orders 
GROUP BY Customer 
HAVING SUM(OrderPrice)>1000 

Tahminen, bu SUM (OrderPrice) değerini hesaplamak için hesaplama zaman alır. Toplama işlevine yapılan her başvuru için bu maliyet mu katılıyor, yoksa belirli bir sorgu için saklanan sonuç mu?

Veya, bu durumda SQL motoru uygulaması için standart yok mu?

cevap

3

Birçok farklı DBMS ile çalışmış olsam da, bunu yalnızca SQL Server'da kanıtlamanın sonuçlarını göstereceğim. İfadede bir CAST içeren bile bu sorguyu düşünün. Sorgu planına bakarak, sum(cast(number as bigint)) ifadesi yalnızca bir kez alınır ve bu değer DEFINE:([Expr1005]=SUM([Expr1006])) olarak tanımlanır.

set showplan_text on 
select type, sum(cast(number as bigint)) 
from master..spt_values 
group by type 
having sum(cast(number as bigint)) > 100000 

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
    |--Filter(WHERE:([Expr1005]>(100000))) 
     |--Hash Match(Aggregate, HASH:([Expr1004]), RESIDUAL:([Expr1004] = [Expr1004]) DEFINE:([Expr1005]=SUM([Expr1006]))) 
      |--Compute Scalar(DEFINE:([Expr1004]=CONVERT(nchar(3),[mssqlsystemresource].[sys].[spt_values].[type],0), [Expr1006]=CONVERT(bigint,[mssqlsystemresource].[sys].[spt_values].[number],0))) 
       |--Index Scan(OBJECT:([mssqlsystemresource].[sys].[spt_values].[ix2_spt_values_nu_nc])) 

o SEÇ bir sonuç vermezse, çünkü yukarıda çok belirgin olmayabilir, bu yüzden aşağıda sorguya bir *10 ekledik. Artık yeni bir ifadenin fazladan bir hesaplama yapmasını gerektirdiğini gösteren bir ek adım olan DEFINE:([Expr1006]=[Expr1005]*(10)) (aşağıdan yukarıya doğru adımlar) içerdiğine dikkat edin. Yine de, bu, tüm ifadeyi yeniden hesaplayamadığı için optimize edilmiş olsa bile, sadece Expr1005'i alıyor ve bunu 10 ile çarpıyor!

set showplan_text on 
select type, sum(cast(number as bigint))*10 
from master..spt_values 
group by type 
having sum(cast(number as bigint)) > 100000 

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 
    |--Compute Scalar(DEFINE:([Expr1006]=[Expr1005]*(10))) 
     |--Filter(WHERE:([Expr1005]>(100000))) 
      |--Hash Match(Aggregate, HASH:([Expr1004]), RESIDUAL:([Expr1004] = [Expr1004]) DEFINE:([Expr1005]=SUM([Expr1007]))) 
       |--Compute Scalar(DEFINE:([Expr1004]=CONVERT(nchar(3),[mssqlsystemresource].[sys].[spt_values].[type],0), [Expr1007]=CONVERT(bigint,[mssqlsystemresource].[sys].[spt_values].[number],0))) 
         |--Index Scan(OBJECT:([mssqlsystemresource].[sys].[spt_values].[ix2_spt_values_nu_nc])) 

Bu, tüm diğer DBMS en azından önemli olanları yani PostgreSQL, Sybase, Oracle, DB2, Firebird, MySQL de dikkate alınmak nasıl çalıştığını çok muhtemeldir.

İlgili konular