5

同じクエリで同じ集計関数を複数回呼び出すための SQL 実装に関する標準はありますか?

たとえば、一般的なスキーマの例に基づいて、次の例を考えてみましょう。

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

おそらく、SUM(OrderPrice) の値を計算するには計算時間がかかります。このコストは集計関数への参照ごとに発生するのか、それとも特定のクエリの結果が保存されるのか?

または、この場合の SQL エンジン実装の標準はありませんか?

4

1 に答える 1

3

私はさまざまな DBMS を扱ってきましたが、SQL Server でこれを証明した結果のみを示します。式に CAST が含まれている次のクエリを考えてみましょう。クエリ プランを見ると、式sum(cast(number as bigint))は として定義されている 1 回だけ取得されDEFINE:([Expr1005]=SUM([Expr1006]))ます。

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]))

上記では SELECT の結果が表示されないため、わかりにくいかもしれません。そのため*10、以下のクエリに a を追加しました。追加のステップが 1 つ含まれていることに注意してくださいDEFINE:([Expr1006]=[Expr1005]*(10))(ステップは下から上に実行されます)。これは、新しい式が追加の計算を実行する必要があることを示しています。それでも、式全体を再計算するわけではないので、これでも最適化されています。単に、Expr1005 を取得して 10 を掛けているだけです。

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]))

これは、少なくとも PostgreSQL、Sybase、Oracle、DB2、Firebird、MySQL などの主要な DBMS を考慮すると、他のすべての DBMS も同様に機能する可能性が非常に高いです。

于 2012-10-13T21:14:12.247 に答える