Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Wydajność zewnętrznej aplikacji z funkcją

To zależy od typu funkcji:

  1. Jeśli funkcja jest funkcją wbudowaną z wartościami tabelarycznymi, ta funkcja zostanie uznana za "sparametryzowany" widok i SQL Server może wykonać pewne prace optymalizacyjne.

  2. Jeśli funkcja jest wieloetapową funkcją z wartościami tabelarycznymi, jest to trudne dla SQL Server aby zoptymalizować instrukcję i wyjście z SET STATISTICS IO będzie wprowadzać w błąd.

Do następnego testu użyłem AdventureWorks2008 (możesz pobrać tę bazę danych z CodePlex). W tej przykładowej bazie danych możesz znaleźć wbudowaną funkcję z wartościami tabelarycznymi o nazwie [Sprzedaż].[ufnGetCheapestProduct] :

ZMIANA FUNKCJI [Sprzedaż].[ufnGetCheapestProduct](@ProductID INT)RETURNS TABLEASRETURN SELECT dt.ProductID ,dt.UnitPrice FROM ( SELECT d.SalesOrderDetailID ,d.UnitPrice ,d.ProductID ,ROW_NUMBER() OVER( PARTITION BY d.ProductID ORDER BY d.UnitPrice ASC, d.SalesOrderDetailID) RowNumber FROM Sales.SalesOrderDetail d WHERE d.ProductID =@ProductID ) dt WHERE dt.RowNumber =1 

Utworzyłem nową funkcję o nazwie [Sales].[ufnGetCheapestProductMultiStep] . Ta funkcja jest wielokrokową funkcją z wartościami w tabeli :

CREATE FUNCTION [Sales].[ufnGetCheapestProductMultiStep](@ProductID INT)RETURNS @Results TABLE (ProductID INT PRIMARY KEY, UnitPrice MONEY NOT NULL)ASBEGIN INSERT @Results(ProductID, UnitPrice) SELECT dt.ProductID ,dt CenaJednostkowa FROM ( SELECT d.SalesOrderDetailID ,d.UnitPrice ,d.ProductID ,ROW_NUMBER() OVER(PARTITION BY d.ProductID ORDER BY d.UnitPrice ASC, d.SalesOrderDetailID) RowNumber FROM Sales.SalesOrderDetail d.ID produktu =WHERE . ProductID ) dt GDZIE dt.RowNumber =1; RETURN;END 

Teraz możemy przeprowadzić kolejne testy:

--Test 1SELECT p.IDProduktu, p.Name, oa1.*FROM Produkcja.Produkt pOUTER APPLY ( SELECT dt.IDProduktu ,dt.CenaJednostkowa FROM ( SELECT d.SalesOrderDetailID ,d.CenaJednostkowa ,d.IDProduktu , NUMER_WIERZA() OVER(PARTITION BY d.IDProduktu ORDER BY d.CenaJednostkowa ASC, d.SalesOrderDetailID) RowNumber FROM Sales.SalesOrderDetail d WHERE d.ProductID =p.ProductID ) dt WHERE dt.RowNumber =1) oa1-Test 2 p.IDProduktu, p.Nazwa, oa2.*FROM Produkcja.Produkt pOUTER APPLY [Sprzedaż].[ufnGetTanieProdukt](p.IDProduktu) oa2 — Test 3SELECT p.IdProduktu, p.Nazwa, oa3.*FROM Produkcja.Produkt pOUTER ZASTOSUJ [Sprzedaż].[ufnGetCheapestProductMultiStep](p.ProductID) oa3

A to jest wynik z SQL Profiler :

Wniosek :widać to za pomocą zapytania lub wbudowanej funkcji z wartościami tabelarycznymi z OUTER APPLY da taką samą wydajność (odczyty logiczne). Plus:wieloetapowe funkcje z wartościami w tabeli są (zazwyczaj) droższe .

Uwaga :Nie polecam używania SET STATISTICS IO do pomiaru IO dla skalarnych i wieloetapowych funkcji o wartościach tabelarycznych, ponieważ wyniki mogą być błędne. Na przykład dla tych testów wyjście z USTAW STATISTICS IO ON będzie:

--Przetestuj 1 tabelę „Szczegóły zamówienia sprzedaży”. Liczba skanów 504, odczyty logiczne 1513, odczyty fizyczne 0, odczyty z wyprzedzeniem 0, odczyty logiczne LOB 0, odczyty fizyczne LOB 0, odczyty LOB z wyprzedzeniem 0. Tabela „Produkt”. Liczba skanów 1, odczyty logiczne 5, odczyty fizyczne 0, odczyty z wyprzedzeniem 0, odczyty logiczne modułu 0, odczyty fizyczne modułu 0, odczyty z wyprzedzeniem modułu 0. ---Test 2 Tabela „Szczegóły zamówienia sprzedaży”. Liczba skanów 504, odczyty logiczne 1513, odczyty fizyczne 0, odczyty z wyprzedzeniem 0, odczyty logiczne LOB 0, odczyty fizyczne LOB 0, odczyty LOB z wyprzedzeniem 0. Tabela „Produkt”. Liczba skanów 1, odczyty logiczne 5, odczyty fizyczne 0, odczyty z wyprzedzeniem 0, odczyty logiczne modułu 0, odczyty fizyczne modułu 0, odczyty z wyprzedzeniem modułu 0.--Test 3Tabela „#064EAD61”. Liczba skanów 504, odczyty logiczne 1008 /*BŁĄD*/, odczyty fizyczne 0, odczyty z wyprzedzeniem 0, odczyty logiczne lobu 0, odczyty fizyczne lobu 0, odczyty z wyprzedzeniem lobu 0. Tabela „Produkt”. Liczba skanów 1, odczyty logiczne 5, odczyty fizyczne 0, odczyty z wyprzedzeniem 0, odczyty logiczne lobu 0, odczyty fizyczne lobu 0, odczyty loba z wyprzedzeniem 0. 


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. dodaj +- 1 rok w SQL Server

  2. Jak określić liczbę dni w miesiącu w SQL Server?

  3. serwer sql przekonwertować datetime na inną strefę czasową?

  4. Pierwszy dzień roboczy bieżącego miesiąca – SQL Server

  5. Wybierz znak cyrylicy w SQL