sql >> データベース >  >> RDS >> Sqlserver

マルチステートメントテーブル値関数とインラインテーブル値関数

    マットのコメントを調査する際に、私は元のステートメントを修正しました。彼は正しいです。インラインテーブル値関数(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にコピー



    1. EMCLIによるブラックアウト

    2. Apache、MariaDB、PHPをサポートするUbuntuへのLaravelのインストール

    3. AndroidのSQLiteデータベースにJSONデータを挿入します

    4. SQL Serverエラー206:オペランドタイプの衝突