웹에서 호출하면 저장 프로 시저가 느리고 Management Studio에서 빠르게


97

웹 응용 프로그램에서 호출 될 때마다 시간 초과되는 저장 프로 시저가 있습니다.

Sql Profiler를 실행하고 시간이 초과 된 호출을 추적하고 마침내 다음을 발견했습니다.

  1. 동일한 인수를 사용하여 MS SQL Management Studio 내에서 명령문을 실행하면 (실제로 SQL 프로필 추적에서 프로 시저 호출을 복사하여 실행했습니다.) 평균 5 ~ 6 초 만에 완료됩니다.
  2. 그러나 웹 응용 프로그램에서 호출하면 30 초 이상 (추적 중)이 걸리므로 웹 페이지가 실제로 시간 초과됩니다.

내 웹 응용 프로그램에 자체 사용자가 있다는 사실 외에도 모든 것이 동일합니다 (동일한 데이터베이스, 연결, 서버 등). 웹 응용 프로그램의 사용자와 함께 스튜디오에서 직접 쿼리를 실행하려고 시도했으며 6 개 이상 걸리지 않습니다. 비서.

무슨 일이 일어나고 있는지 어떻게 알 수 있습니까?

트레이스가 실제 절차에 지연이 있음을 분명히 보여 주므로 BLL> DAL 레이어 또는 테이블 어댑터를 사용한다는 사실과 관련이 없다고 가정합니다. 그게 제가 생각할 수있는 전부입니다.

편집 나는 이 링크 에서 ADO.NET ARITHABORT이 true로 설정한다는 것을 알았습니다. 대부분의 경우 좋지만 언젠가는 이런 일이 발생하며 제안 된 해결 with recompile방법은 저장된 proc에 옵션을 추가하는 것입니다. 제 경우에는 작동하지 않지만 이와 매우 유사한 것 같습니다. ADO.NET의 다른 기능이나 사양을 어디에서 찾을 수 있는지 아는 사람이 있습니까?


1
반환되는 데이터의 양과 관련이있을 수 있습니다.
Barry Kaye 2011

@Barry : 아니요, 관리 스튜디오에서 동일한 절차 (추적에서도 복사 됨-동일한 매개 변수를 의미 함)를 실행하므로 6 초 이내에 실행됩니다.
iamserious

@Jayantha : 요점은 sp가 느리다는 것이 아니라 ado.net과 sql 사이의 무언가가 있다는 것입니다. 나는 sp가 어떤 차이를 만들지 모르겠습니다.
iamserious

2
SP가 많은 데이터 (예 : image / text / varchar (max) 열)를 반환합니까? 클라이언트에서 소비하는 데이터의 양은 엄청나게 많아서 많은 시간이 걸립니다. SSMS는 더 효율적인 문제로 이러한 결과 집합을 차단합니다.
Tim Schmelter 2011

답변:


79

과거에 비슷한 문제가 발생 했으므로이 질문에 대한 해결책을 찾고 싶습니다. OP에 대한 Aaron Bertrand의 의견 은 웹에서 실행할 때 Query 시간 초과로 이어 졌지만 SSMS 에서 실행하면 매우 빠르며 질문이 중복되지는 않지만 대답은 귀하의 상황에 매우 잘 적용될 수 있습니다.

본질적으로 SQL Server에 손상된 캐시 실행 계획이있는 것처럼 들립니다. 웹 서버에서 나쁜 계획을 세우고 있지만 ARITHABORT 플래그에 다른 설정이 있기 때문에 SSMS는 다른 계획에 도달합니다 (그렇지 않으면 특정 쿼리 / 저장된 프로 시저에 영향을주지 않음).

ADO.NET에서 T-SQL 저장 프로 시저를 호출하면 SqlTimeoutException이 발생 하고보다 완전한 설명과 해결 방법이있는 다른 예제를 참조하십시오 .


이것들은 몇 가지 흥미로운 단서이며, 그들에 대해 더 많이 읽고 몇 번 후에 다시 돌아올 것입니다. 감사합니다.
iamserious

44
안녕, 캐시를 삭제 DBCC DROPCLEANBUFFERS하고 DBCC FREEPROCCACHE속임수를 썼는지! 실행 계획이 어떻게 든 손상되었거나 업데이트되지 않은 것 같습니다. 나는 그것이 영구적 인 해결책이라고 의심 스럽습니다. 한번 손상 될 수 있다면 다시 할 수 있습니다. 그래서 나는 여전히 그럴듯한 원인을 조사하고 있습니다. 웹 앱이 다시 작동하기 때문에 부담감을 느낄 필요가 없습니다. 고맙습니다.
iamserious

2
@iamserious-감사합니다! 저장 프로 시저를 변경 한 후 시간 초과 문제가 발생했습니다. 그런 다음 위에서 언급 한 두 개의 DBCC 명령을 실행하여 문제를 해결했습니다.
Induster

5
@Mangist : 이것은 복잡한 문제이기 때문에 은색 총알은 없지만 문제를 일으키는 쿼리에 대한 힌트를 사용 OPTIMIZE FOR하거나 OPTION(Recompile)쿼리 할 수 있습니다. 이 기사 에서는 문제에 대해 자세히 설명합니다. Entity Framework가 쿼리를 생성하는 경우이 게시물 은 쿼리에 쿼리 힌트를 추가하는 방법을 제공하는 것으로 보입니다.
StriplingWarrior

8
모든 실행 계획을 지우는 DBCC DROPCLEANBUFFERS 및 DBCC FREEPROCCACHE를 실행하는 대신 문제 저장 프로 시저를 삭제하고 다시 만들 수 있습니다.
jnoreiga

51

또한 쿼리가 웹에서 느리고 SSMS에서 빠르게 실행되는 것을 경험했으며 결국 문제가 매개 변수 스니핑이라는 것을 알게되었습니다.

나를위한 수정 사항은 sproc에서 사용되는 모든 매개 변수를 지역 변수로 변경하는 것이 었습니다.

예. 변화:

ALTER PROCEDURE [dbo].[sproc] 
    @param1 int,
AS
SELECT * FROM Table WHERE ID = @param1 

에:

ALTER PROCEDURE [dbo].[sproc] 
    @param1 int,
AS
DECLARE @param1a int
SET @param1a = @param1
SELECT * FROM Table WHERE ID = @param1a

이상하게 보이지만 문제가 해결되었습니다.


3
와, 나는 같은 문제가 있었고 이것이 효과가있을 것이라고 믿지 않았지만 작동했습니다.
Lac Ho

1
Zane, 이것이 문제를 영구적으로 해결할 것인지 아니면 다시 돌아올 수 있는지 알고 있습니까? 감사합니다!
Lac Ho

1
이렇게 변경 한 이후로 저장 프로 시저의 속도에 문제가 없었습니다.
Zane 2013

1
와우, 내 문제도 해결되었습니다! 이것은 SQL 서버의 버그 여야합니다. 엄청난 성능 향상을 위해 MSSQL이 내부적으로 내부적으로 로컬로 변환 할 수 있는데 왜 SQL 작성자가이 바보 같은 골대를 뛰어 넘도록 강요합니까?
HerrimanCoder

3
proc을 변경하면 새 실행 계획이 생성되어 솔루션이 실제로 입력 변수를 로컬 변수에 복사하는 것이 아니라 새 실행 계획을 생성하도록 할 수 있습니까 (허용 된 솔루션에서 설명 됨)?
Garland Pope

10

스팸이 아니라 다른 사람들에게 도움이되는 해결책으로 우리 시스템은 높은 수준의 시간 초과를 보았습니다.

사용하여 재 컴파일 할 저장 프로 시저를 설정하려고했는데 sp_recompile이로 인해 하나의 SP에 대한 문제가 해결되었습니다.

궁극적으로 SP의 타이밍 아웃, 사용하여, 그렇게 해본 적이없는 많은 것이 있었다 그 많은 수 있었다 DBCC DROPCLEANBUFFERSDBBC FREEPROCCACHE시간 제한의 입사 비율이 크게 하락했다 - 고립 된 사건이 아직도있다, 나는 계획의 재생을 의심 곳 일부는 복용입니다 그리고 일부 SP의 성능이 실제로 저조하고 재평가가 필요한 경우도 있습니다.


1
감사합니다. sp_recompile 명령을 사용하여 재 컴파일 절차를 표시하는 것은 저에게 효과가 DBCC DROPCLEANBUFFERS있었고 DBCC FREEPROCCACHE차이가 없었습니다.
Steve

4

웹 응용 프로그램이 SP를 호출하기 전에 만들어진 다른 DB 호출이 트랜잭션을 열린 상태로 유지하는 것일 수 있습니까? 웹 애플리케이션에서이 SP를 호출 할 때이 SP가 대기하는 이유 일 수 있습니다. 웹 응용 프로그램의 일부 이전 작업이이 문제를 일으키는 지 확인하기 위해 웹 응용 프로그램에서 호출을 분리 (새 페이지에 배치)한다고 말합니다.


1
안녕하세요 @Tundey, 통화를 분리했지만 여전히 약 30 초가 걸리고 시간이 초과되었습니다. 그래서 그것은 의사 소통 사이에 무언가가되어야합니다.
iamserious

1

저장 프로 시저 (제 경우에는 테이블 함수)를 다시 컴파일하는 것이 효과적이었습니다.


1

@Zane이 매개 변수 스니핑 때문일 수 있다고 말한 것처럼. 동일한 동작을 경험했고 프로 시저의 실행 계획과 sp의 모든 문을 연속으로 살펴 보았습니다 (프로 시저를 구성하는 모든 문을 복사하고 매개 변수를 변수로 선언하고 변수에 대해 동일한 값을 매개 변수가 있었다). 그러나 실행 계획은 완전히 달랐습니다. sp 실행에는 3-4 초가 걸렸고 정확히 동일한 값을 가진 행의 문이 즉시 반환되었습니다.

실행 계획

인터넷 검색을 한 후 그 동작에 대한 흥미로운 읽기를 찾았 습니다. 응용 프로그램에서 느리게, SSMS에서 빠르십니까?

프로 시저를 컴파일 할 때 SQL Server는 @fromdate의 값이 변경되는 것을 알지 못하지만 @fromdate의 값이 NULL이라는 가정하에 프로 시저를 컴파일합니다. NULL을 사용한 모든 비교는 UNKNOWN을 산출하므로 @fromdate가 런타임에이 값을 계속 가지고 있으면 쿼리는 행을 전혀 반환 할 수 없습니다. SQL Server가 입력 값을 최종 진실로 받아들이면 테이블에 전혀 액세스하지 않는 상수 스캔만으로 계획을 구성 할 수 있습니다 (이 예제를 보려면 SELECT * FROM Orders WHERE OrderDate> NULL 쿼리를 실행) . 그러나 SQL Server는 @fromdate가 런타임에 어떤 값을 가지고 있더라도 올바른 결과를 반환하는 계획을 생성해야합니다. 한편, 모든 가치에 가장 적합한 계획을 세울 의무는 없습니다. 따라서 행이 반환되지 않는다고 가정하므로 SQL Server는 Index Seek를 결정합니다.

문제는 내가 null로 남을 수있는 매개 변수가 있고 null로 전달되면 기본값으로 초기화된다는 것입니다.

create procedure dbo.procedure
    @dateTo datetime = null
begin
    if (@dateTo is null)
    begin
        select @dateTo  = GETUTCDATE()
    end

    select foo
    from dbo.table
    where createdDate < @dateTo
end

내가 그것을 변경 한 후

create procedure dbo.procedure
    @dateTo datetime = null
begin
    declare @to datetime = coalesce(@dateTo, getutcdate())

    select foo
    from dbo.table
    where createdDate < @to
end 

그것은 다시 매력처럼 작동했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.