マットのコメントを調査する際に、私は元のステートメントを修正しました。彼は正しいです。インラインテーブル値関数(ITVF)とマルチステートメントテーブル値関数(MSTVF)は、どちらも単にSELECTステートメントを実行するだけでも、パフォーマンスに違いがあります。 SQL Serverは、ITVFをVIEW
のように扱います。 問題のテーブルの最新の統計を使用して実行プランを計算するという点で。 MSTVFは、SELECTステートメントの内容全体をテーブル変数に詰め込んでからそれに結合することと同じです。したがって、コンパイラはMSTVFのテーブルでテーブル統計を使用できません。したがって、すべてが同じであれば(めったにありませんが)、ITVFはMSTVFよりも優れたパフォーマンスを発揮します。私のテストでは、完了時間のパフォーマンスの違いはごくわずかでしたが、統計の観点からは顕著でした。
あなたの場合、2つの機能は機能的に同等ではありません。 MSTV関数は、呼び出されるたびに追加のクエリを実行し、最も重要なこととして、顧客IDをフィルタリングします。大規模なクエリでは、オプティマイザは、渡されたcustomerIdごとに関数を呼び出す必要があるため、他のタイプの結合を利用できません。ただし、MSTV関数を次のように書き直した場合:
CREATE FUNCTION MyNS.GetLastShipped()
RETURNS @CustomerOrder TABLE
(
SaleOrderID INT NOT NULL,
CustomerID INT NOT NULL,
OrderDate DATETIME NOT NULL,
OrderQty INT NOT NULL
)
AS
BEGIN
INSERT @CustomerOrder
SELECT a.SalesOrderID, a.CustomerID, a.OrderDate, b.OrderQty
FROM Sales.SalesOrderHeader a
INNER JOIN Sales.SalesOrderHeader b
ON a.SalesOrderID = b.SalesOrderID
INNER JOIN Production.Product c
ON b.ProductID = c.ProductID
WHERE a.OrderDate = (
Select Max(SH1.OrderDate)
FROM Sales.SalesOrderHeader As SH1
WHERE SH1.CustomerID = A.CustomerId
)
RETURN
END
GO
クエリでは、オプティマイザーはその関数を1回呼び出して、より適切な実行プランを作成できますが、それでも、同等のパラメーター化されていないITVSまたはVIEW
よりも優れているわけではありません。 。
ITVFは、可能な場合はMSTVFよりも優先されます。これは、テーブルの列からのデータ型、null可能性、および照合が、マルチステートメントテーブル値関数でこれらのプロパティを宣言し、重要なことに、ITVFからより良い実行計画が得られるためです。私の経験では、ITVFがVIEWよりも優れたオプションであるが、走行距離が異なる可能性がある状況は多くありません。
マットに感謝します。
追加
これが最近出てきたのを見たので、これはウェインシェフィールドによって行われたインラインテーブル値関数とマルチステートメント関数のパフォーマンスの違いを比較する優れた分析です。
彼の元のブログ投稿。
SQLServerCentralにコピー