[英]to gain SQL Server performance can I use something like set-based SQL with INSERT to temp-table?
使用SQL Server 2008 R2
我从此函数有一个20秒的查询,该查询正在使用游标,While循环和AND调用另一个函数。
根据显示的代码-改善此瓶颈性能的最佳方法是什么?
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
您应该可以使用一个选择。
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
乍一看,我们绝对可以消除CURSOR
。 尽管用WHILE
循环替换它是一种解决方案,但我们可以更进一步,通过使用APPLY
子句直接针对行中的每个值调用函数,从而完全消除循环。
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
此代码未经测试,但应该可以工作。 如果您有任何问题,请告诉我。
另外,在您的问题中,您从第一个查询(光标所在的位置)中省略了表名,因此我将YourTable
放在其中作为占位符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.