2015-01-21 1 views
0

복잡한 보고서 (아래 예제와 유사)를 사용하면 42 초 만에 52 개 항목 만 반환됩니다. (느리지 만 복잡한 결합은 있습니다.) 다음과 같이하면 속도가 크게 느려집니다. 외부 선택의 작업에 대한 CTE 쿼리 속도가 크게 저하되었습니다.

  1. 가 결과에 각 항목을 항목의 직렬화 된 목록을 가져 외부 선택의 열을 추가 (1백50초 추가) - 기능을 참조하십시오.
  2. 결과를 변수 테이블에 삽입합니다 (120 초 추가).하지만 평면화를 적용하면 (1) 문제는 줄어들지 만 시가는 줄이지 ​​않기를 바랍니다.

내가 어떻게 실행을 이해한다는 점은 선택에서 논리가 처음 실행되고 논리가 실행된다는 것입니다 (52 개 결과 항목에 대해서만 수행되어야 함). 그러나 (1) 시나리오로 정확히 52 개의 항목을 실행하면 바깥 쪽 CTE 선택시을 사용할 때 추가 된 150 초에 비해 7 초 밖에 걸리지 않습니다.

왜 이렇게 될 수 있으며 확장 된 실행 시간없이 열을 추가 할 수 있습니까?

CREATE FUNCTION PriorShippers 
(
    @customerId nchar(5) 
) 
RETURNS varchar(500) 
AS 
BEGIN 
    DECLARE @return varchar(500); 

    with data as 
    (
     select distinct S.CompanyName from Customers C 
      join Orders O on C.CustomerID = O.CustomerID 
      join Shippers S on O.ShipVia = S.ShipperID 
      where C.CustomerID = @customerId 

    ) select @return = STUFF((select CompanyName + ' ' from data FOR XML PATH('')),1,0,'') 

    return @return 
END 

쿼리 (I는 Northwind 데이터베이스를 사용 - Install Instructions here를 SQL 2012)

DECLARE @categories TABLE 
(
    Name varchar(100), 
    SourceCountry varchar(100) 
); 
insert into @categories VALUES ('Seafood', 'US'); 
insert into @categories VALUES ('Beverages', 'US'); 
insert into @categories VALUES ('Condiments', 'US'); 
insert into @categories VALUES ('Dairy Products', 'India'); 
insert into @categories VALUES ('Grains/Cereals', 'India'); 

with data as 
(
    select C.CustomerID, C.CompanyName, 
     (CASE WHEN EXISTS(select * from Orders O where O.CustomerID = C.CustomerID) THEN 
      (select count(distinct CAT.CategoryID) from Orders O 
       join [Order Details] OD on O.OrderID = OD.OrderID 
       join Products P on OD.ProductID = P.ProductID 
       join Categories CAT on P.CategoryID = CAT.CategoryID 
      where EXISTS(select * from @categories where Name = CAT.CategoryName AND SourceCountry = 'US')) 
     ELSE 0 END) as 'US Orders', 

     (CASE WHEN EXISTS(select * from Orders O where O.CustomerID = C.CustomerID) THEN 
      (select count(distinct CAT.CategoryID) from Orders O 
       join [Order Details] OD on O.OrderID = OD.OrderID 
       join Products P on OD.ProductID = P.ProductID 
       join Categories CAT on P.CategoryID = CAT.CategoryID 
      where EXISTS(select * from @categories where Name = CAT.CategoryName AND SourceCountry = 'India')) 
     ELSE 0 END) as 'India Orders' 

    from Customers C 

) select top 10 CompanyName, [US Orders], [India Orders] 
    -- Below: Adding this have significant slow down 
    , dbo.PriorShippers(CustomerID) 
    from data where [US Orders] > 0 Order By [US Orders] 

답변

0

선택한 각 행에 대해 사용자 정의 함수를 실행하고 있습니다. 간단히 말해서 은 그렇게하지 않습니다.

기능 코드를 보고서 내에서 직접 DTE로 옮깁니다.

또한 귀하의 계산에 대한 조인이 동일한 것으로 나타났습니다. 이들은 전체 쿼리의 성능을 향상시키기 위해 간단하게 참여할 수있는 세 번째 DTE의 주요 후보자처럼 보입니다.

+0

안녕하세요, Mike, 함수가 CTE (serialize해야하는 고유 선택)를 사용하기 때문에 선택 항목을 중첩 할 수 없습니다. 나는 함수를 호출하는 것이 일반적으로 좋은 생각이 아니라는 것을 이해하지만, 내 관심사는 실행 시간의 엄청난 증가라고한다. 만약 내가 같은 결과 (52) 항목을 CTE와 마찬가지로 가변 테이블 선택 호출 사용자 기능에 추가하면 7 초와 추가 150 초가 소요됩니다. 또한 값을 선택하는 것만으로 (사용자 함수 호출없이) 예제에서 경험 한 120 초가 추가됩니다. CTE 외부 선택이 정상 선택과 다른 점을 이해하려고합니다. –

관련 문제