오래 전에이 문제가 있었는데 나에게 맞는 해결 방법을 발견하고 잊어 버렸습니다.
그러나 이제 그에 대한 질문 이 있으므로이 문제를 기꺼이 제기하겠습니다.
몇 가지 테이블을 매우 간단한 방식으로 정렬하는 뷰가 있습니다 (오더 + 오더 라인).
where
절 없이 쿼리 하면 뷰는 수백만 줄을 반환합니다.
그러나 아무도 그렇게 그렇게 부르지 않습니다. 일반적인 검색어는
select * from that_nasty_view where order_number = 123456;
이렇게하면 5m 중 약 10 개의 레코드가 반환됩니다.
중요한 것은 : 뷰에는 윈도우 함수가 포함되어 rank()
있으며, 뷰는 항상 쿼리가 사용되는 필드로 정확하게 분할됩니다.
rank() over (partition by order_number order by detail_line_number)
이제이 뷰가 쿼리 문자열에서 리터럴 매개 변수로 쿼리되면 위와 같이 정확하게 행을 리턴합니다. 실행 계획은 괜찮습니다.
- 인덱스는 인덱스를 사용하여 두 테이블 모두에서 검색
order_number
합니다 (10 개의 행을 반환 함). - 작은 결과를 반환하는 창을 계산합니다.
- 선택 중입니다.
그러나 뷰가 매개 변수화 된 방식으로 호출되면 상황이 악화됩니다.
Index scan
인덱스를 무시하고 모든 테이블에. 5m 행을 반환합니다.- 큰 조인.
- 모든
partition
s에 대한 창 계산 (약 500k 창). Filter
5m에서 10 개의 행을 가져옵니다.- 고르다
이는 매개 변수가 관련된 모든 경우에 발생합니다. SSMS 일 수 있습니다.
declare @order_number int = 123456;
select * from that_nasty_view where order_number = @order_number;
Excel과 같은 ODBC 클라이언트 일 수 있습니다.
select * from that_nasty_view where order_number = ?
또는 SQL 연결이 아닌 매개 변수를 사용하는 다른 클라이언트 일 수 있습니다.
창 함수가보기에서 제거되면 매개 변수로 조회되는지 여부에 관계없이 완벽하게 빠르게 실행됩니다.
내 해결 방법은 문제가되는 기능을 제거하고 나중에 다시 적용하는 것이 었습니다.
그러나 무엇을 제공합니까? SQL Server 2008에서 창 기능을 처리하는 방식이 실제로 버그입니까?
order_number
기본 키가 아닙니다. 그것은이다 int not null
두 테이블에에 클러스터되지 않은 인덱스.
OPTION (RECOMPILE)
도움을?