SQLSERVER 파라미터 탐지 문제 란 무엇 입 니까?

'후 탐'이라는 단 어 를 들 으 면 해커 와 관련 이 있다 고 생각 하 시 겠 죠?도 구 를 사용 하여 파 라 메 터 를 탐색 한 다음 에 캡 처 합 니 다.탈 바 지 는 o(∩∩)o 。
사실 저 는 여러분 이 너무 민감 하 다 고 생각 합 니 다.사실 이 글 은 데이터 뱅 크 안전 과 아무런 관계 가 없 으 며 실제 적 으로 데이터 뱅 크 의 성능 향상 과 관련 이 있 습 니 다.
SQLSERVER 포럼 이 있다 고 믿 으 시 면 많 지도 적지 도 않 아 요.'파라미터 탐지'라 는 글 자 를 보 실 수 있 을 거 예요.
여기 세 편의 댓 글 이 있 는데 모두 파라미터 탐지 기 를 다 루 고 있 습 니 다.
http://social.msdn.microsoft.com/Forums/zh-CN/sqlserverzhchs/thread/caccb7f3-8366-4954-8f8a-145eb6bca9dd
http://msdn.microsoft.com/zh-cn/magazine/ee236412.aspx
http://social.msdn.microsoft.com/Forums/zh-CN/sqlserverzhchs/thread/bfbe54de-ac00-49e9-a83b-f97a60bf74ef
아래 에 저 는 테스트 데이터 베 이 스 를 백업 하 는 파일 을 드 리 겠 습 니 다.안에 표 와 테스트 데이터 가 있 습 니 다.여러분 은 다운로드 하 셔 도 됩 니 다.왜냐하면 제 가 아래 에 사용 하 는 테스트 표 는 모두 이 데이터 베이스 에 있 기 때 문 입 니 다.
데이터베이스 복원 만 하면 됩 니 다.이 데이터 베 이 스 는 SQL 2005 버 전 입 니 다.데이터베이스 이름:AdventureWorks
다음은 세 장의 시계 만 사용 할 수 있 습 니 다.표 안에 색인 이 있 습 니 다.
[Production].[Product] [SalesOrderHeader_test] [SalesOrderDetail_test]
데이터베이스 다운로드 링크:AdventureWorks

사실 쉽게 말 하면 매개 변수 가 나의 통속 적 인 해석 은 SQLSERVER 가 코 로 구체 적 인 매개 변수 가 얼마 인지 냄새 를 맡 지 못 한 다 는 것 이다.
그래서 그 는 가장 적합 한 실행 계획 을 선택 하여 당신 의 조 회 를 집행 할 수 없 기 때문에 매개 변수 탐색 은 좋 지 않 은 현상 입 니 다.
매개 변수 탐지 기 를 진정 으로 이해 하려 면 다음 두 개의 저장 과정 을 먼저 만 들 수 있 습 니 다.
저장 프로시저 1:

USE [AdventureWorks]
GO
DROP PROC Sniff
GO
CREATE PROC Sniff(@i INT)
AS
SELECT COUNT(b.[SalesOrderID]),SUM(p.[Weight])
FROM [dbo].[SalesOrderHeader_test] a
INNER JOIN [dbo].[SalesOrderDetail_test] b
ON a.[SalesOrderID]=b.[SalesOrderID]
INNER JOIN [Production].[Product] p
ON b.[ProductID]=p.[ProductID]
WHERE a.[SalesOrderID]=@i
GO
저장 프로시저 2:

 1 USE [AdventureWorks] 2 GO 3 DROP PROC Sniff2 4 GO 5 CREATE PROC Sniff2(@i INT) 6 AS 7 DECLARE @j INT 8 SET @j=@i 9 SELECT COUNT(b.[SalesOrderID]),SUM(p.[Weight])10 FROM [dbo].[SalesOrderHeader_test] a11 INNER JOIN [dbo].[SalesOrderDetail_test] b12 ON a.[SalesOrderID]=b.[SalesOrderID]13 INNER JOIN [Production].[Product] p14 ON b.[ProductID]=p.[ProductID]15 WHERE a.[SalesOrderID]=@j16 GO
그리고 다음 두 가지 테스트 를 해 보도 록 하 겠 습 니 다.
테스트 1:

--   :
USE [AdventureWorks]
GO
DBCC freeproccache
GO
EXEC [dbo].[Sniff] @i = 500000 -- int
--    ,      nested loops       
GO

EXEC [dbo].[Sniff] @i = 75124 -- int
--        ,     nested loops     
GO

테스트 2:

--   :

USE [AdventureWorks]
GO
DBCC freeproccache
GO
SET STATISTICS PROFILE ON
EXEC [dbo].[Sniff] @i = 75124 -- int
--    ,      hash match       
GO

EXEC [dbo].[Sniff] @i = 50000 -- int
--        ,     hash match     
GO

위의 두 테스트 에서 실행 계획 의 중용 부작용 을 똑똑히 볼 수 있다.
데이터 분포 차이 가 매우 크 기 때문에 50000 과 75124 는 자신 이 생 성 한 집행 계획 에 만 좋 은 성능 을 가진다.
상대방 이 생 성 한 실행 계획 을 사용 하면 성능 이 떨어진다.인자 50000 반환 결과 집합 이 비교적 작 습 니 다.
그래서 성능 저하 가 심 하지 않 습 니 다.매개 변수 75124 반환 결과 가 집 대 된 것 은 뚜렷 한 성능 이 떨 어 졌 고 두 실행 계획 의 차 이 는 10 배 에 가깝다.
타인 이 생 성 한 실행 계획 을 다시 사용 하기 때문에 발생 하 는 이러한 풍토 불복 현상 에 대해 SQSERVER 는'파라미터 탐지 parameter sniffing'이라는 전문 명사 가 있다.
문장의 실행 계획 은 변수의 값 에 민감 하기 때문에 다시 실행 계획 을 실행 하 는 데 성능 문제 가 발생 할 수 있 습 니 다.바로 제 가 위 에서 말 한 것 입 니 다.

SQLSERVER 는 코 로 구체 적 인 매개 변수 가 얼마 인지 냄새 를 맡 지 못 하기 때문에 가장 적합 한 실행 계획 을 선택 하여 조 회 를 수행 할 수 없습니다.

로 컬 변수의 영향
그러면 parameter sniffing 문제 가 있 는 저장 과정 에 대해 로 컬 변 수 를 사용 하면 어떻게 됩 니까?
다음은 테스트 3 을 보십시오.이번 에는 서로 다른 변수 값 을 사용 할 때 계획 캐 시 를 비우 고 다시 컴 파일 하도록 합 니 다.

--   
USE [AdventureWorks]
GO
DBCC freeproccache
GO
SET STATISTICS TIME ON
SET STATISTICS PROFILE ON
EXEC [dbo].[Sniff] @i = 50000 -- int
GO


--   
USE [AdventureWorks]
GO
DBCC freeproccache
GO
SET STATISTICS TIME ON
SET STATISTICS PROFILE ON
EXEC [dbo].[Sniff] @i = 75124 -- int
GO


--   
USE [AdventureWorks]
GO
DBCC freeproccache
GO
SET STATISTICS TIME ON
SET STATISTICS PROFILE ON
EXEC [dbo].[Sniff2] @i = 50000 -- int
GO


--   
USE [AdventureWorks]
GO
DBCC freeproccache
GO
SET STATISTICS TIME ON
SET STATISTICS PROFILE ON
EXEC [dbo].[Sniff2] @i = 75124 -- int
GO


그들의 집행 계획 을 보면:
첫 번 째 문장 과 두 번 째 문장 에 대해 SQL 은 컴 파일 할 때 변수의 값 을 알 기 때문에 EstimateRows 를 할 때 매우 정확하게 하고 그들 에 게 가장 적합 한 실행 계획 을 선택 했다.
하지만 세 번 째 문장 과 네 번 째 문장 에 대해 서 는 SQLSERVER 가@j 의 값 이 얼마 인지 모 르 기 때문에 EstimateRows 를 할 때 대 입 된@i 값 이 얼마 든
일률적으로@j 와 같은 예측 결 과 를 주다.그래서 두 가지 실행 계획 은 똑 같 습 니 다.
파라미터 탐지 의 해결 방법
매개 변수 탐지 문제 가 발생 하 는 빈도 가 높 지 않다.그 는 일부 표 안의 데이터 분포 가 고 르 지 않 거나 사용자 가 가 져 온 매개 변수 값 이 고 르 지 않 은 상황 에서 만 발생 할 수 있다.
편폭 의 원인 으로 나 는 구체 적 으로 말 하지 않 고 단지 귀납 만 할 뿐이다.
(1)exec()방식 으로 동적 SQL 실행
저장 과정 에서 문 구 를 직접 실행 하 는 것 이 아니 라 문 구 를 변 수 를 가 져 와 문자열 을 만 들 고 exec()와 같은 명령 을 동적 문 구 를 실행 하 게 한다 면,
그러면 SQL 은 이 말 이 실 행 될 때 동적 문 구 를 컴 파일 합 니 다.
이때 SQL 은 변수의 값 을 알 고 최 적 화 된 실행 계획 생 성에 따라 매개 변수 탐지 문 제 를 돌아 갑 니 다.

--         Sniff,       
USE [AdventureWorks]
GO
DROP PROC NOSniff
GO
CREATE PROC NOSniff(@i INT)
AS
DECLARE @cmd VARCHAR(1000)
SET @cmd='SELECT COUNT(b.[SalesOrderID]),SUM(p.[Weight])
FROM [dbo].[SalesOrderHeader_test] a
INNER JOIN [dbo].[SalesOrderDetail_test] b
ON a.[SalesOrderID]=b.[SalesOrderID]
INNER JOIN [Production].[Product] p
ON b.[ProductID]=p.[ProductID]
WHERE a.[SalesOrderID]='
EXEC(@cmd+@i)
GO
(2)로 컬 변수 local variable 사용
(3)문장 에 query hint 를 사용 하여 실행 계획 을 지정 합 니 다.
select,insert,update,delete 문장의 마지막 에"option()"의 자구
SQLSERVER 가 생 성 할 실행 계획 에 대해 지도 합 니 다.DBA 가 문제 의 소 재 를 알 게 되면 hint 를 넣 는 방식 으로 유도 할 수 있다.
SQL 은 가능 한 모든 변수 값 에 대해 비교적 안전 한 실행 계획 을 만 듭 니 다.

USE [AdventureWorks]
GO
DROP PROC NoSniff_QueryHint_Recompile
GO
CREATE PROC NoSniff_QueryHint_Recompile(@i INT) 
AS
SELECT COUNT(b.[SalesOrderID]),SUM(p.[Weight])
FROM [dbo].[SalesOrderHeader_test] a
INNER JOIN [dbo].[SalesOrderDetail_test] b
ON a.[SalesOrderID]=b.[SalesOrderID]
INNER JOIN [Production].[Product] p
ON b.[ProductID]=p.[ProductID]
WHERE a.[SalesOrderID]=@i
OPTION(RECOMPILE)
GO
(4)Plan Guide
아래 의 방법 으로 원래 매개 변수 탐지 문제 가 있 는 저장 과정 인'Sniff'에서 sniffing 문 제 를 해결 할 수 있 습 니 다.

USE [AdventureWorks]
GO
EXEC [sys].[sp_create_plan_guide]
@name=N'Guide1',
@stmt=N'SELECT COUNT(b.[SalesOrderID]),SUM(p.[Weight])
FROM [dbo].[SalesOrderHeader_test] a
INNER JOIN [dbo].[SalesOrderDetail_test] b
ON a.[SalesOrderID]=b.[SalesOrderID]
INNER JOIN [Production].[Product] p
ON b.[ProductID]=p.[ProductID]
WHERE a.[SalesOrderID]=@i',
@type=N'OBJECT',
@module_or_batch=N'Sniff',
@params=NULL,
@hints=N'option(optimize for(@i=75124))';
GO
플랜 가이드 에 대해 서 는 일반적인 구문 튜 닝 에 도 사용 할 수 있다.
드디어 해 결 됐 습 니 다.테스트 데 이 터 를 해 야 해서 오래 했 네요~~
총결산
위 에서 말 한 것 은 소 편 이 여러분 에 게 소개 한 SQLSERVER 파라미터 탐지 문제 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다!

좋은 웹페이지 즐겨찾기