/ / aby uzyskać wydajność SQL Servera, czy mogę użyć czegoś takiego jak SQL oparty na zestawie z INSERT do temp-table? - sql, sql-server, performance, tsql

aby uzyskać wydajność SQL Servera, czy mogę użyć czegoś takiego jak SQL oparty na zestawach z INSERT do temp-table? - sql, sql-server, performance, tsql

Korzystanie z SQL Server 2008 R2

Mam 20-sekundowe zapytanie z tej funkcji, która używa kursora, pętli while i AND wywołuje inną funkcję.

Na podstawie pokazanego kodu - jaki byłby najlepszy sposób na poprawę wydajności tego wąskiego gardła?

USE [DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[ufnGetForUser] (@UserName VARCHAR(100))
RETURNS @User TABLE (
ID INT
,Name VARCHAR(40)
,ParentID INT
,CompanyID INT
,CompanyName VARCHAR(100)
,CompanyDisplayName VARCHAR(100)
,AnotherID INT
,AnotherName VARCHAR(50)
)
AS
BEGIN
DECLARE @List TABLE (
ID INT
,Name VARCHAR(40)
,ParentID INT
)

DECLARE List CURSOR
FOR
SELECT ID
FROM YourTable WITH (NOLOCK)
WHERE CompanyID IN (
SELECT companyid
FROM UserToCompany
WHERE UserName = @UserName
)

DECLARE @ID AS INT

OPEN List

FETCH List
INTO @id

WHILE (@@FETCH_STATUS = 0)
BEGIN
INSERT INTO @List
SELECT *
FROM ufnIncludeWithChildren(@ID)

FETCH List
INTO @ID
END

CLOSE List

DEALLOCATE List

INSERT INTO @User
SELECT DISTINCT a.ID
,a.Name
,a.ParentID
,c.CompanyID
,c.CompanyName
,c.CompanyDisplayName
,d.AnotherID
,d.AnotherName
FROM @List a
JOIN YourTable b ON a.ID = b.ID
JOIN CompanyInfo c ON b.CompanyID = c.CompanyID
JOIN Anothers d ON b.AnotherID = d.AnotherID

RETURN
END

Odpowiedzi:

3 dla odpowiedzi № 1

Powinieneś być w stanie użyć jednego wyboru.

USE [DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[ufnGetForUser] (@UserName VARCHAR(100))
RETURNS @User TABLE (
ID INT
,Name VARCHAR(40)
,ParentID INT
,CompanyID INT
,CompanyName VARCHAR(100)
,CompanyDisplayName VARCHAR(100)
,AnotherID INT
,AnotherName VARCHAR(50)
)
AS
BEGIN
INSERT INTO @User
SELECT DISTINCT a.ID
,a.Name
,a.ParentID
,c.CompanyID
,c.CompanyName
,c.CompanyDisplayName
,d.AnotherID
,d.AnotherName
FROM UserToCompany u
JOIN CompanyInfo c ON u.CompanyID = c.CompanyID
CROSS APPLY ufnIncludeWithChildren(yt.ID) a
JOIN YourTable b ON a.ID = b.ID
JOIN Anothers d ON b.AnotherID = d.AnotherID
WHERE u.UserName = @UserName
RETURN
END

2 dla odpowiedzi nr 2

Na pierwszy rzut oka możemy zdecydowanie wyeliminować CURSOR. Podczas zastępowania go przez WHILE Pętla, ponieważ w moim komentarzu jest jedno rozwiązanie, możemy pójść o krok dalej i całkowicie wyeliminować pętlę, używając APPLY klauzula wywoływania funkcji bezpośrednio dla każdej wartości w wierszu.

ALTER FUNCTION [dbo].[ufnGetForUser] (@UserName VARCHAR(100))
RETURNS @User TABLE (
ID INT
,Name VARCHAR(40)
,ParentID INT
,CompanyID INT
,CompanyName VARCHAR(100)
,CompanyDisplayName VARCHAR(100)
,AnotherID INT
,AnotherName VARCHAR(50)
)
AS
BEGIN
DECLARE @List TABLE (
ID INT
,Name VARCHAR(40)
,ParentID INT
)

INSERT INTO @List
SELECT sfn.*
FROM YourTable yt WITH (NOLOCK)
CROSS APPLY ufnIncludeWithChildren(yt.ID) sfn
WHERE yt.CompanyID IN (
SELECT companyid
FROM UserToCompany
WHERE UserName = @UserName
)

INSERT INTO @User
SELECT DISTINCT a.ID
,a.Name
,a.ParentID
,c.CompanyID
,c.CompanyName
,c.CompanyDisplayName
,d.AnotherID
,d.AnotherName
FROM @List a
JOIN  b ON a.ID = b.ID
JOIN CompanyInfo c ON b.CompanyID = c.CompanyID
JOIN Anothers d ON b.AnotherID = d.AnotherID

RETURN
END

Ten kod nie jest testowany, ale powinien działać. Daj mi znać, jeśli masz jakieś problemy.

Również w swoim pytaniu pominąłeś nazwę tabeli z pierwszego zapytania (w którym miałeś kursor), więc wstawiłem YourTable tam jako symbol zastępczy.