sql >> Database >  >> RDS >> Sqlserver

Multi-statement Table Valued Function vs Inline Table Valued Function

Bij het onderzoeken van de opmerking van Matt heb ik mijn oorspronkelijke verklaring herzien. Hij heeft gelijk, er zal een verschil in prestatie zijn tussen een inline table valued function (ITVF) en een multi-statement table valued function (MSTVF), zelfs als ze allebei gewoon een SELECT-instructie uitvoeren. SQL Server behandelt een ITVF enigszins als een VIEW in die zin dat het een uitvoeringsplan berekent op basis van de laatste statistieken over de tabellen in kwestie. Een MSTVF komt overeen met het proppen van de volledige inhoud van uw SELECT-instructie in een tabelvariabele en vervolgens daaraan deelnemen. De compiler kan dus geen tabelstatistieken gebruiken voor de tabellen in de MSTVF. Dus als alle dingen gelijk zijn (wat ze zelden zijn), zal de ITVF beter presteren dan de MSTVF. In mijn tests was het prestatieverschil in voltooiingstijd verwaarloosbaar, maar vanuit statistisch oogpunt was het merkbaar.

In uw geval zijn de twee functies niet functioneel equivalent. De MSTV-functie doet elke keer dat deze wordt aangeroepen een extra query en, belangrijker nog, filtert op de klant-ID. In een grote query zou de optimizer geen voordeel kunnen halen uit andere typen joins, omdat deze de functie voor elke doorgegeven customerId zou moeten aanroepen. Als u uw MSTV-functie echter als volgt herschreef:

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

In een query zou de optimizer die functie één keer kunnen aanroepen en een beter uitvoeringsplan kunnen bouwen, maar het zou nog steeds niet beter zijn dan een gelijkwaardige, niet-geparametriseerde ITVS of een VIEW .

ITVF's zouden waar mogelijk de voorkeur moeten krijgen boven MSTVF's, omdat de datatypes, nullabiliteit en sortering van de kolommen in de tabel, terwijl u die eigenschappen in een multi-statement tabel waardeert, functie en, belangrijker nog, u betere uitvoeringsplannen krijgt van de ITVF. In mijn ervaring heb ik niet veel omstandigheden gevonden waarin een ITVF een betere optie was dan een VIEW, maar de kilometerstand kan variëren.

Met dank aan Matt.

Toevoeging

Aangezien ik dit onlangs zag opduiken, is hier een uitstekende analyse uitgevoerd door Wayne Sheffield, waarin het prestatieverschil tussen Inline Table Valued-functies en Multi-Statement-functies wordt vergeleken.

Zijn originele blogpost.

Kopiëren op SQL Server Central



  1. De beste manier om het aantal resultaten te krijgen voordat LIMIT werd toegepast

  2. Kraaienpootnotatie

  3. SELECT max(x) retourneert null; hoe kan ik ervoor zorgen dat het 0 teruggeeft?

  4. Top 5 tools voor gegevensmodellering voor SQL Server