2013-04-26 4 views
7

매개 변수가있는 테이블 값 함수 인 CROSS APPLY에 문제가 있습니다. 다음은 단순화 의사 코드 예제 :테이블 값 함수 제한 성능을 적용한 경우

SELECT * 
FROM (
    SELECT lor.* 
    FROM LOT_OF_ROWS_TABLE lor 
    WHERE ... 
) AS lor 
CROSS APPLY dbo.HeavyTableValuedFunction(lor.ID) AS htvf 
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID 
WHERE ... 
  • 내부는 LOT_OF_ROWS_TABLE 많은 행을 반환 테이블에 선택합니다.
  • 테이블 조인 LOT_OF_ROWS_TABLEANOTHER_TABLE은 하나 또는 몇 개의 행만 반환합니다.
  • 테이블 값 함수는 매우 많은 시간이 걸리고 많은 행을 호출 할 때 선택 시간이 매우 길어집니다.

내 문제 :

기능은 모든 행에 대해 호출은 ANOTHER_TABLE에 가입하면 데이터가 제한 될 것이라는 사실에 관계없이 LOT_OF_ROWS_TABLE에서 돌아왔다.

선택 항목은 표시된 형식이어야하며 실제로 생성되며 실제로는 훨씬 어려워집니다.

나는 그것을 다시 할 때, 그것은 매우 빠르게 할 수 있지만, 이렇게 다시 할 수 없습니다

어떤 설정이 아니면 : 내가 좋아하는 것

SELECT * 
FROM (
    SELECT lor.* 
    FROM LOT_OF_ROWS_TABLE lor 
    WHERE ... 
) AS lor 
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID 
CROSS APPLY dbo.HeavyTableValuedFunction(at.ID) AS htvf 
WHERE ... 

알고 힌트 또는 select가 마지막으로 제한된 행에 대해서만 함수를 호출하도록 강요합니다.

감사합니다.

는 편집 :

테이블 반환 함수는 매우 복잡하다 : http://pastebin.com/w6azRvxR. 우리가 말하는 선택은 "사용자 구성"이며 ​​생성 : http://pastebin.com/bFbanY2n.

2 개 부분

SELECT lor.*,at.* into #tempresult 
FROM (
    SELECT lor.* 
    FROM LOT_OF_ROWS_TABLE lor 
    WHERE ... 
) lor 
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID 
WHERE ... 

이제 테이블 반환 함수가 걸리는 부분의 시간을 두 테이블 변수 또는 임시 테이블을 사용하여에이 쿼리를 나눌 수

+0

명백한 어쩌면 : 쿼리 텍스트에서 조인 순서 만 변경할 수있는 경우. 그런 다음 FORCE_ORDER 쿼리 힌트를 사용할 수 있습니다. 코드가 어떻게 생성됩니까? 그 목적으로 행동을 바꿀 수있는 방법이 없습니까? –

+0

'dbo.HeavyTableValuedFunction (..)'의 멀티 라인 테이블 반환 함수를 인라인 테이블 반환 함수로 변경하십시오. – RBarryYoung

+0

@RBarryYoung : 너무 복잡하여 인라인 함수로 다시 작성할 수 없습니다. –

답변

2

바로

SELECT * FROM #tempresult 
CROSS APPLY dbo.HeavyTableValuedFunction(#tempresult.ID) AS htvf 
+0

입니다. 'lor'테이블과 교차 적용은 함께 있어야하기 때문에이 작업을 수행 할 수 없습니다. 복잡한 생성 쿼리 내에서 하나의 유닛을 나타내며 (더 많은 유닛이 조인 될 수 있음) 마지막으로 필터링됩니다. (실제로는 another_table은 최종 제한을 나타내는 일부 레코드가있는 임시 테이블 변수입니다). –

1

나는 이것이 무엇을 믿고 당신이 찾고있는.

Plan Forcing Scenario: Create a Plan Guide to Force a Plan Obtained from a Rewritten Query

기본적으로 설명을 다시 작성하는 조인 올바른 순서를 사용하여 생성 된 계획을 얻을 수있는 쿼리를. 그런 다음 해당 계획을 저장하고 기존 쿼리를 변경하지 않아도 저장 한 계획을 사용할 수 있습니다.

내가 넣은 BOL 링크도 조인을 다른 순서로 놓고 FORCE ORDER 힌트를 사용하여 쿼리를 다시 작성하는 구체적인 예를 제공합니다. 그런 다음 sp_create_plan_guild을 사용하여 다시 작성된 쿼리에서 계획을 가져 와서 원래 쿼리에서 사용하십시오.

+0

아쉽게도 선택 항목이 "사용자 구성"이며 ​​생성되어 더 많은 다른 테이블에 가입 할 수 있습니다. 계획을 예측할 수 없습니다. –

0

예 및 아니오 ...결과를 비교하기 위해 샘플 데이터 IN 및 결과 OUT없이 달성하고자하는 것을 보간하기가 어렵습니다.

내가 알고 싶습니다

: 어떤 설정이

있는가 또는 힘은 결국 제한 행에 대한 함수를 호출하는 선택 뭔가 힌트 나?

그래서 내가 직접 문을 직접 (! 삼년 이상) 위의 질문에 답변 해 드리겠습니다 :

하는 당신은 CTE에 대해 배우고 CROSS의 차이는 INNER에 비해 을 적용해야 JOIN 및 귀하의 케이스에 CROSS APPLY를 사용하는 이유는 입니다. 함수에서 코드를 가져와 CTE를 사용하여 단일 SQL 문에 을 적용 할 수 있습니다.

예 :

읽기 thisthis. 기본적으로

,이 같은 ...

WITH t2o AS 
     (
     SELECT t2.*, ROW_NUMBER() OVER (PARTITION BY t1_id ORDER BY rank) AS rn 
     FROM t2 
     ) 
SELECT t1.*, t2o.* 
FROM t1 
INNER JOIN 
     t2o 
ON  t2o.t1_id = t1.id 
     AND t2o.rn <= 3 

는 ONCE 원하는 날짜를 추정하는 쿼리를 적용하고 CTE를 사용하여 다음 CROSS APPLY를 사용하여 두 번째 SQL을 적용 할 수 있습니다.

선택의 여지가 없습니다. 하나의 SQL에서 수행하려는 작업을 수행 할 수 없습니다.