programing

SQL Server:빠른 쿼리, 그러나 절차에서 느린 쿼리

itsource 2023. 4. 7. 23:18
반응형

SQL Server:빠른 쿼리, 그러나 절차에서 느린 쿼리

쿼리는 빠르게 실행됩니다.

DECLARE @SessionGUID uniqueidentifier
SET @SessionGUID = 'BCBA333C-B6A1-4155-9833-C495F22EA908'

SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

서브트리 비용: 0.502

그러나 동일한 SQL을 스토어드 프로시저에 넣는 작업은 느리고 실행 계획은 전혀 다릅니다.

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS
SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

EXECUTE ViewOpener @SessionGUID

서브트리 비용: 19.2

나는 도망쳤다

sp_recompile ViewOpener

또한 여전히 동일하게 실행되며(나쁘게 실행), 저장 프로시저를 로 변경했습니다.

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS
SELECT *, 'recompile please'
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

다시 돌아와서 다시 컴파일을 하도록 속이고 있습니다.

새 계획을 생성하기 위해 저장 프로시저를 삭제하고 다시 만들었습니다.

디코이 변수를 사용하여 재컴파일을 강제하여 파라미터 스니핑을 방지해 보았습니다.

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier AS

DECLARE @SessionGUIDbitch uniqueidentifier
SET @SessionGUIDbitch = @SessionGUID

SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUIDbitch
ORDER BY CurrencyTypeOrder, Rank

저장 프로시저를 정의해 보았습니다.

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier 
WITH RECOMPILE
AS
SELECT *
FROM Report_Opener
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

따라서 계획은 캐시되지 않으며 실행 시 재컴파일을 강제로 실행하려고 시도한 적이 있습니다.

EXECUTE ViewOpener @SessionGUID WITH RECOMPILE

그건 도움이 안 됐어

프로시저를 다이내믹 SQL로 변환해 보았습니다.

CREATE PROCEDURE dbo.ViewOpener @SessionGUID uniqueidentifier 
WITH RECOMPILE AS
DECLARE @SQLString NVARCHAR(500)

SET @SQLString = N'SELECT *
   FROM Report_OpenerTest
   WHERE SessionGUID = @SessionGUID
   ORDER BY CurrencyTypeOrder, Rank'

EXECUTE sp_executesql @SQLString,
N'@SessionGUID uniqueidentifier',
@SessionGUID

그건 도움이 안 됐어

'Report_Opener"는 인덱스가 없는 뷰입니다.뷰는 기본 테이블만 참조합니다.테이블에는 계산 컬럼이 포함되어 있지 않습니다.인덱스화 되어 있는지 여부입니다.

그 재미로 나는 경치를 만들어 보려고 했다.

SET ANSI_NULLS ON
SET QUOTED_IDENTIFER ON

그것으로는 해결되지 않았다.

왜 그런 거야?

  • 쿼리가 빠르다
  • 조회를 보기로 이동하고 보기에서 빠르게 선택
  • 저장 프로시저에서 뷰에서 선택하는 것이 40배 느립니다.

뷰의 정의를 스토어드 프로시저로 직접 이동시켜 보았습니다(비즈니스 규칙 3개를 위반하고 중요한 캡슐화가 깨짐).그 때문에 속도가 약 6배 느려집니다.

저장 프로시저 버전이 이렇게 느린 이유는 무엇입니까?애드혹 SQL을 다른 종류의 애드혹 SQL보다 더 빠르게 실행하는 SQL Server를 설명할 수 있는 것은 무엇입니까?

안 하는 게 낫겠다

  • SQL을 코드에 삽입하다
  • 코드를 아예 바꾸다

    Microsoft SQL Server  2000 - 8.00.2050 (Intel X86)
    Mar  7 2008 21:29:56
    Copyright (c) 1988-2003 Microsoft Corporation
    Standard Edition on Windows NT 5.2 (Build 3790: Service Pack 2)
    

그러나 파라미터 스니핑이 아닌 경우 SQL Server가 쿼리를 실행하는 SQL Sever만큼 빠르게 실행되지 못하는 이유는 무엇입니까?


내 다음 도전은 이 모든 것을StoredProcedureAStoredProcedureBStoredProcedureCStoredProcedureD보기를 쿼리합니다.

스토어드 프로시저가 스토어드 프로시저를 호출하거나 UDF를 호출하거나 스토어드 프로시저를 호출하거나 UDF를 호출하여 뷰를 조회하도록 합니다.


요약하자면, QA에서는 다음이 빠르게 실행되지만 스토어드 프로시저에서는 느려집니다.

원본:

--Runs fine outside of a stored procedure
SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

sp_executesql:

--Runs fine outside of a stored procedure
DECLARE @SQLString NVARCHAR(500)
SET @SQLString = N'SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank'

EXECUTE sp_executesql @SQLString,
        N'@SessionGUID uniqueidentifier',
        @SessionGUID

EXEC(@sql):

--Runs fine outside of a stored procedure
DECLARE @sql NVARCHAR(500)
SET @sql = N'SELECT *
FROM Report_OpenerTest
WHERE SessionGUID = '''+CAST(@SessionGUID AS varchar(50))+'''
ORDER BY CurrencyTypeOrder, Rank'

EXEC(@sql)

실행 계획

좋은 계획:

      |--Sort(ORDER BY:([Expr1020] ASC, [Currencies].[Rank] ASC))
           |--Compute Scalar(DEFINE:([Expr1020]=If ([Currencies].[CurrencyType]='ctCanadianCash') then 1 else If ([Currencies].[CurrencyType]='ctMiscellaneous') then 2 else If ([Currencies].[CurrencyType]='ctTokens') then 3 else If ([Currencies].[CurrencyType]
                |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Openers].[OpenerGUID]))
                     |--Filter(WHERE:((([Currencies].[IsActive]<>0 AND [Currencies].[OnOpener]<>0) AND ((((((([Currencies].[CurrencyType]='ctUSCoin' OR [Currencies].[CurrencyType]='ctMiscellaneousUS') OR [Currencies].[CurrencyType]='ctUSCash') OR [Currencies].
                     |    |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Currencies].[CurrencyGUID], [Openers].[OpenerGUID]) WITH PREFETCH)
                     |         |--Nested Loops(Left Outer Join)
                     |         |    |--Bookmark Lookup(BOOKMARK:([Bmk1016]), OBJECT:([GrobManagementSystemLive].[dbo].[Windows]))
                     |         |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([Openers].[WindowGUID]))
                     |         |    |         |--Bookmark Lookup(BOOKMARK:([Bmk1014]), OBJECT:([GrobManagementSystemLive].[dbo].[Openers]))
                     |         |    |         |    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_SessionGUID]), SEEK:([Openers].[SessionGUID]=[@SessionGUID]) ORDERED FORWARD)
                     |         |    |         |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Windows].[IX_Windows]), SEEK:([Windows].[WindowGUID]=[Openers].[WindowGUID]) ORDERED FORWARD)
                     |         |    |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                     |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID] AND [OpenerDetails].[CurrencyGUID]=[Currenc
                     |--Hash Match(Cache, HASH:([Openers].[OpenerGUID]), RESIDUAL:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]))
                          |--Stream Aggregate(DEFINE:([Expr1006]=SUM(If (((([Currencies].[CurrencyType]='ctMiscellaneous' OR [Currencies].[CurrencyType]='ctTokens') OR [Currencies].[CurrencyType]='ctChips') OR [Currencies].[CurrencyType]='ctCanadianCoin') OR [
                               |--Nested Loops(Inner Join, OUTER REFERENCES:([OpenerDetails].[CurrencyGUID]) WITH PREFETCH)
                                    |--Nested Loops(Inner Join)
                                    |    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_OneOpenerPerSession]), SEEK:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                    |    |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                    |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[PK_Currencies_CurrencyGUID]), SEEK:([Currencies].[CurrencyGUID]=[OpenerDetails].[CurrencyGUID]) ORDERED FORWARD)

나쁜 계획

       |--Sort(ORDER BY:([Expr1020] ASC, [Currencies].[Rank] ASC))
            |--Compute Scalar(DEFINE:([Expr1020]=If ([Currencies].[CurrencyType]='ctCanadianCash') then 1 else If ([Currencies].[CurrencyType]='ctMiscellaneous') then 2 else If ([Currencies].[CurrencyType]='ctTokens') then 3 else If ([Currencies].[Currency
                 |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Openers].[OpenerGUID]))
                      |--Filter(WHERE:((([Currencies].[IsActive]<>0 AND [Currencies].[OnOpener]<>0) AND ((((((([Currencies].[CurrencyType]='ctUSCoin' OR [Currencies].[CurrencyType]='ctMiscellaneousUS') OR [Currencies].[CurrencyType]='ctUSCash') OR [Currenc
                      |    |--Nested Loops(Left Outer Join, OUTER REFERENCES:([Currencies].[CurrencyGUID], [Openers].[OpenerGUID]) WITH PREFETCH)
                      |         |--Filter(WHERE:([Openers].[SessionGUID]=[@SessionGUID]))
                      |         |    |--Concatenation
                      |         |         |--Nested Loops(Left Outer Join)
                      |         |         |    |--Table Spool
                      |         |         |    |    |--Hash Match(Inner Join, HASH:([Windows].[WindowGUID])=([Openers].[WindowGUID]), RESIDUAL:([Windows].[WindowGUID]=[Openers].[WindowGUID]))
                      |         |         |    |         |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Windows].[IX_Windows_CageGUID]))
                      |         |         |    |         |--Table Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Openers]))
                      |         |         |    |--Table Spool
                      |         |         |         |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                      |         |         |--Compute Scalar(DEFINE:([Openers].[OpenerGUID]=NULL, [Openers].[SessionGUID]=NULL, [Windows].[UseChipDenominations]=NULL))
                      |         |              |--Nested Loops(Left Anti Semi Join)
                      |         |                   |--Clustered Index Scan(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[IX_Currencies_CurrencyType]))
                      |         |                   |--Row Count Spool
                      |         |                        |--Table Spool
                      |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID] AND [OpenerDetails].[CurrencyGUID]=[Cu
                      |--Hash Match(Cache, HASH:([Openers].[OpenerGUID]), RESIDUAL:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]))
                           |--Stream Aggregate(DEFINE:([Expr1006]=SUM([partialagg1034]), [Expr1007]=SUM([partialagg1035]), [Expr1008]=SUM([partialagg1036]), [Expr1009]=SUM([partialagg1037]), [Expr1010]=SUM([partialagg1038]), [Expr1011]=SUM([partialagg1039]
                                |--Nested Loops(Inner Join)
                                     |--Stream Aggregate(DEFINE:([partialagg1034]=SUM(If (((([Currencies].[CurrencyType]='ctMiscellaneous' OR [Currencies].[CurrencyType]='ctTokens') OR [Currencies].[CurrencyType]='ctChips') OR [Currencies].[CurrencyType]='
                                     |    |--Nested Loops(Inner Join, OUTER REFERENCES:([OpenerDetails].[CurrencyGUID]) WITH PREFETCH)
                                     |         |--Clustered Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[OpenerDetails].[IX_OpenerDetails_OpenerGUIDCurrencyGUID]), SEEK:([OpenerDetails].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)
                                     |         |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Currencies].[PK_Currencies_CurrencyGUID]), SEEK:([Currencies].[CurrencyGUID]=[OpenerDetails].[CurrencyGUID]) ORDERED FORWARD)
                                     |--Index Seek(OBJECT:([GrobManagementSystemLive].[dbo].[Openers].[IX_Openers_OneOpenerPerSession]), SEEK:([Openers].[OpenerGUID]=[Openers].[OpenerGUID]) ORDERED FORWARD)

나쁜 쪽은 600만 행에 열을 올리고 있고, 다른 쪽은 그렇지 않습니다.

참고: 이것은 쿼리 조정에 대한 질문이 아닙니다.번개처럼 빠르게 진행되는 질문이 있습니다.저장 프로시저에서 SQL Server를 빠르게 실행하기만 하면 됩니다.

원래 포스터와 같은 문제가 있었지만 인용된 답변은 저에게 문제를 해결해주지 않았습니다.저장 프로시저에서 쿼리가 여전히 느리게 실행되었습니다.

'파라미터 스니핑'이라는 답을 또 찾았어요. 고마워요 옴니부즈.스토어드 프로시저 쿼리에서 "로컬 변수"를 사용하는 것으로 요약되지만, 자세한 내용은 원본을 읽어보십시오. 예를 들어 다음과 같습니다.

슬로웨이:

CREATE PROCEDURE GetOrderForCustomers(@CustID varchar(20))
AS
BEGIN
    SELECT * 
    FROM orders
    WHERE customerid = @CustID
END

빠른 방법:

CREATE PROCEDURE GetOrderForCustomersWithoutPS(@CustID varchar(20))
AS
BEGIN
    DECLARE @LocCustID varchar(20)
    SET @LocCustID = @CustID

    SELECT * 
    FROM orders
    WHERE customerid = @LocCustID
END

이를 통해 실행 시간이 5분 이상에서 약 6-7초로 단축되었습니다.

문제를 발견했습니다. 다음은 저장 프로시저의 느린 버전과 빠른 버전의 스크립트입니다.

dbo.ViewOpener__RenamedForCruachan__Slow.PRC

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS OFF 
GO

CREATE PROCEDURE dbo.ViewOpener_RenamedForCruachan_Slow
    @SessionGUID uniqueidentifier
AS

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank
GO

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

dbo.ViewOpener__RenamedForCruachan__Fast.PRC

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

CREATE PROCEDURE dbo.ViewOpener_RenamedForCruachan_Fast
    @SessionGUID uniqueidentifier 
AS

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank
GO

SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

당신이 차이를 발견하지 못했다면, 나는 당신을 비난하지 않습니다.차이는 저장 프로시저에 전혀 없습니다.고속 0.5 비용 쿼리를 600만 행의 고속 스풀을 실행하는 쿼리로 변환하는 차이:

저속: SET ANSI_NULLS OFF

고속: SET ANSI_NULLS ON


뷰에는 다음과 같은 join 절이 있기 때문에 이 답변도 의미가 있을 수 있습니다.

(table.column IS NOT NULL)

몇 가지 .NULL련되되다


설명은 Query Analizer로 돌아가 실행함으로써 더욱 입증됩니다.

SET ANSI_NULLS OFF

.

DECLARE @SessionGUID uniqueidentifier
SET @SessionGUID = 'BCBA333C-B6A1-4155-9833-C495F22EA908'

.

SELECT *
FROM Report_Opener_RenamedForCruachan
WHERE SessionGUID = @SessionGUID
ORDER BY CurrencyTypeOrder, Rank

그리고 문의가 느립니다.


따라서 저장 프로시저에서 쿼리가 실행되고 있기 때문이 아닙니다.문제는 Enterprise Manager의 연결 기본 옵션이ANSI_NULLS off 보다ANSI_NULLS onQA(QA)

Microsoft는 KB296769에서 이 사실을 인정하고 있습니다(BUG: SQL Enterprise Manager를 사용하여 링크된 서버 개체를 포함하는 저장 프로시저를 생성할 수 없습니다).회피책은 다음과 같습니다.ANSI_NULLS「 」 「 」 、 「 」

Set ANSI_NULLS ON
Go
Create Proc spXXXX as
....

저도 같은 문제에 직면해 있었습니다.이 글은 저에게 큰 도움이 되었습니다만, 투고된 답변 중 구체적인 문제를 해결한 것은 없었습니다.다른 사람에게 도움이 되길 바라며 나에게 효과가 있는 솔루션을 게시하고 싶었다.

https://stackoverflow.com/a/24016676/814299

쿼리 마지막에 OPTIME FOR(@now UNKNOWN)을 추가합니다.

데이터베이스에 대해 이 작업을 수행합니다.같은 문제가 있습니다.한 데이터베이스에서는 정상적으로 동작하지만 SSIS Import를 사용하여 이 데이터베이스를 다른 데이터베이스로 복사하면(통상적인 복원이 아님) 대부분의 저장 프로시저에서 이 문제가 발생합니다.그래서 구글을 좀 더 검색한 후에 Pinal Dave의 블로그를 찾았습니다(그러나 저는 Pinal Dave의 투고를 대부분 접했고 많은 도움이 되었습니다).

데이터베이스에 대해 다음 쿼리를 실행하면 문제가 해결됩니다.

EXEC sp_MSforeachtable @command1="print '?' DBCC DBREINDEX ('?', ' ', 80)"
GO
EXEC sp_updatestats
GO 

이게 도움이 됐으면 좋겠다.나를 도와준 다른 사람들의 도움을 받은 것뿐이다.

나는 이 문제를 겪고 있었다.질문 내용은 다음과 같습니다.

select a, b, c from sometable where date > '20140101'

저장 프로시저는 다음과 같이 정의되었습니다.

create procedure my_procedure (@dtFrom date)
as
select a, b, c from sometable where date > @dtFrom

데이터 타입을 datetime과 voila로 변경했습니다!30분에서 1분으로!

create procedure my_procedure (@dtFrom datetime)
as
select a, b, c from sometable where date > @dtFrom

이번에는 문제를 발견하셨군요.다음 번에 운이 나빠도 파악할 수 없는 경우에는 계획 동결을 사용하여 잘못된 실행 계획에 대한 걱정을 없앨 수 있습니다.

Report_Opener 테이블의 통계정보 및 인덱스를 재구축해 본 적이 있습니까?통계가 데이터베이스가 처음 inauguated되었을 때의 데이터를 계속 보여주면 SP의 모든 recomplies는 아무런 가치가 없습니다.

파라미터가 null이 되지 않음을 옵티마이저가 확인할 수 있기 때문에 초기 쿼리 자체는 빠르게 작동합니다.SP의 경우 옵티마이저는 파라미터가 결코 null이 되지 않음을 확신할 수 없습니다.

저는 보통 반대합니다만(이 경우는 진짜 이유가 있는 것 같습니다만), SP 버전의 쿼리에 대한 힌트를 제공해 본 적이 있습니까?SQL Server가 이 두 인스턴스에서 다른 실행 계획을 준비하고 있는 경우 힌트를 사용하여 계획이 처음과 일치하도록 사용할 인덱스를 지시할 수 있습니까?

예를 들면, 여기를 참조해 주세요.

편집: 여기에 질문 플랜을 투고해 주실 수 있으면, 그 플랜의 차이를 특정할 수 있습니다.

두 번째: SQL-2000 고유 링크 업데이트.아래로 스크롤해야 하는데, 두 번째 "테이블 힌트"가 있습니다.

세 번째: "Bad" 쿼리가 [IX_Openers_Session]를 무시하는 것 같습니다."Openers" 테이블의 GUID - 인덱스 힌트를 추가하여 해당 인덱스를 사용하도록 강제할 수 있습니까?

그럴 가능성은 거의 없겠지만, 독자 분의 관찰된 행동이 비정상적이기 때문에, 그것을 확인할 필요가 있고, 다른 누구도 그것에 대해 언급하지 않았습니다.

모든 개체가 dbo에 의해 소유되고 자신이나 다른 사용자가 소유한 악성 복사본이 없다고 확신하십니까?

이상한 동작을 본 적이 있는 것은, 실제로는 2개의 오브젝트의 카피가 있기 때문이며, 그 카피는, 무엇을 지정해 누구로서 로그인하고 있는지에 따라서 다릅니다.예를 들어, 동일한 이름의 뷰 또는 프로시저의 복사본이 두 개 있지만 다른 소유자가 소유할 수 있습니다. 즉, 데이터베이스에 dbo로 로그온하지 않고 개체를 생성할 때 dbo를 개체 소유자로 지정하는 것을 잊어버리는 상황이 발생할 수 있습니다.

텍스트에서 소유자를 지정하지 않고 몇 가지 작업을 수행하고 있는 것에 주의해 주십시오.예를 들어,

sp_recompile ViewOpener

예를 들어 dbo와 [다른 사용자]가 소유한 viewOpener의 복사본이 두 개 있는 경우 지정하지 않으면 실제로 다시 컴파일할 수 있는 복사본은 상황에 따라 달라집니다.Report_Opener 뷰와 마찬가지로 2개의 복사본이 있는 경우(및 두 복사본은 사양 또는 실행 계획이 다를 수 있음) 사용하는 것은 상황에 따라 달라집니다.또한 소유자를 지정하지 않기 때문에 애드혹 쿼리가 1개를 사용하고 컴파일된 프로시저가 다른 복사본을 사용할 수도 있습니다.

말씀드린 바와 같이 가능성은 낮지만 문제가 되는 것은 단순히 잘못된 장소에서 버그를 찾는 것일 수 있기 때문에 가능한 일이므로 확인해야 합니다.

--해결 방법은 다음과 같습니다.

create procedure GetOrderForCustomers(@CustID varchar(20))

as

begin

select * from orders

where customerid = ISNULL(@CustID, '')

end

- 바로 그거야.

Session이라는 이름에서 알 수 있듯이 어리석게 들릴 수 있습니다.GUID입니다만, 이 열은 Report_Opener의 고유 식별자입니까?그렇지 않은 경우 올바른 유형으로 캐스팅하여 시도하거나 변수를 올바른 유형으로 선언할 수 있습니다.

Sproc의 일부로 작성된 계획이 의도하지 않게 작동하여 큰 테이블에서 내부 캐스팅을 수행할 수 있습니다.

다른 생각이 있어요.다음 테이블 기반 함수를 만들면 어떻게 됩니까?

CREATE FUNCTION tbfSelectFromView
(   
    -- Add the parameters for the function here
    @SessionGUID UNIQUEIDENTIFIER
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT *
    FROM Report_Opener
    WHERE SessionGUID = @SessionGUID
    ORDER BY CurrencyTypeOrder, Rank
)
GO

그리고 다음 문장을 사용하여 이 중에서 선택합니다(이것을 SP에 넣어도 됩니다).

SELECT *
FROM tbfSelectFromView(@SessionGUID)

SQL Server는 잘못된 가정을 하고 있기 때문에 이 가정을 수정하지 않으면 안 될 수도 있습니다(모든 사람이 이미 코멘트하고 있습니다).스텝을 추가하기는 싫지만 다른 원인이 무엇인지 잘 모르겠습니다.

언급URL : https://stackoverflow.com/questions/440944/sql-server-query-fast-but-slow-from-procedure

반응형