2013-12-12 2 views
-2

쿼리 속도를 높이고 싶지만 이전 쿼리에서 느린 기능을 사용하여 과거 쿼리가 어떻게 바뀌 었는지 확인할 수 없습니다. 이는 쿼리의 속도를 높여 주지만 전체 쿼리를 함께 사용하면 더 빠릅니다. 문제는 각 하위 쿼리에 대해 내 주 테이블을 호출해야한다는 것입니다. 아래의 10 개 항목은 전체 내용이 약간 문제이므로 쿼리의 일부입니다. 문제의 원인을 알려줘야합니다.메인 테이블 호출로 인해 천천히 실행되는 SQL 쿼리

고맙습니다.

토마스

새로운 코드 -

SELECT DISTINCT CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, msValidFrom) + 1, msValidFrom) AS FLOAT)) AS DATETIME) AS MemMonth, 
    (SELECT COUNT(DISTINCT me_csID) AS Expr1 
    FROM dbo.tblMembershipStatus 
    WHERE (ms_memID IN (@memID)) 
     AND (msDurationType IN (@memType)) 
     AND (CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, MainMonth.msValidFrom) + 1, MainMonth.msValidFrom) AS FLOAT)) AS DATETIME)) 
     BETWEEN CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, msValidFrom) + 1, msValidFrom) AS FLOAT)) AS DATETIME) 
     AND CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, msValidUntil) + 1, msValidUntil) AS FLOAT)) AS DATETIME)) AS active 
FROM tblMembershipStatus AS MainMonth 
WHERE (CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, msValidFrom) + 1, msValidFrom) AS FLOAT)) AS DATETIME) BETWEEN @StartDate AND @EndDate) 
GROUP BY msValidFrom 
ORDER BY MemMonth 

같은 코드를하지만보기 어떻게했는지 -이 단지 부분적인 해답이 여기에 할 일이 많이

SELECT Purple7Master.dbo.fnc_GetMonthStart(msValidFrom) AS [MemMonth], 
    (SELECT COUNT(DISTINCT me_csID) AS Expr1 
    FROM dbo.tblMembershipStatus 
    WHERE (ms_memID IN (@memID)) 
     AND (msDurationType IN (@memType)) 
     AND (Purple7Master.dbo.fnc_GetMonthStart(MainMonth.msValidFrom) 
     BETWEEN Purple7Master.dbo.fnc_GetMonthStart(msValidFrom) 
     AND Purple7Master.dbo.fnc_GetMonthStart(msValidUntil))) AS [active]  
FROM tblMembershipStatus AS MainMonth 
WHERE (Purple7Master.dbo.fnc_GetMonthStart(msValidFrom) BETWEEN @StartDate AND @EndDate) 
GROUP BY Purple7Master.dbo.fnc_GetMonthStart(msValidFrom) 
ORDER BY MemMonth 
+0

실행 계획은 어디에 있습니까? – Kermit

답변

0

있습니다를 너부터 시작해.

WHERE (CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, msValidFrom) + 1, msValidFrom) AS FLOAT)) AS DATETIME) BETWEEN @StartDate AND @EndDate) 

처음에는 이것이 매우 비효율적입니다. 테이블의 모든 행을 처리하고 전체 테이블 스캔을 강제 실행합니다.

당신은

WHERE msValidFrom between @calculated_StartDate and @calculated_endDate 

및 msValidFrom 병 속도까지 가지 이상의 인덱스를 생성처럼 뭔가를 변경해야합니다.

당신은 또한 단지를 선택하기 전에 약간의 석회질을 수행 할 수 있습니다

declare @Calculated_date datetime 
SET @calcualted_date = cast(floor(......... @no_calculated_date.....)) 
0

날 당신이 무엇을 바꿔하려고하자, 어떤 것으로 나타남하면 쿼리를 죽이고 완전히 낭비 변환 할 수 있습니다. @StartDate, @EndDate 특정 회원 ID @ememID 및 멤버쉽 기간 @emem 유형

표 구조 및 샘플 데이터가 도움이 될 것입니다. 귀하의 전환이 무엇을하고 있으며 왜 그것이 과잉 일 수 있는지보십시오.

DatePart(dd, msValidFrom) returns the DAY a member is valid from ex: 12th of the month 
DateAdd(dd, -DatePart(dd, msValidFrom) +1, msValidFrom) is basically saying 
Take Dec 12, subtract 12 days to get to last day of November 30, then add 1 to bring it 
back to the first day of December, so you have the month 12 (December) 

왜 단지

DatePart(mm, msValidFrom) to give you 12 (December). 

SQL을 사용하지 가장 안쪽을 보면

CAST(FLOOR(CAST(DATEADD(dd, - DATEPART(dd, msValidFrom) + 1, msValidFrom) AS FLOAT)) AS DATETIME) AS MemMonth, 

는 ... 처리하는 날짜/시간 구성 요소에 대한.

그 자체로 두통이 간단 해집니다.

은 OUTER WHERE 절, 나는 지금

(ms_memID, msDurationType, msValidFrom) 

ON 당신의 tblMembershipStatus에 인덱스를 가질 것, 도움이됩니다. 당신은 거기에 같은 일을하고 있으며, 날짜에 대한 색인이 있다면.나는 당신의 WHERE 절은 수, 그리고 각각

시작 날짜가 될 것 달의 시작/끝의 적절한 형식

@StartDate = '2013-11-01' (which defaults to 12:00:00 AM) 
@EndDate = '2013-12-01' (which also defaults to 12:00:00 AM) 

같은 당신의 @StartDate 및 @EndDate있을 것

WHERE 
     ms_memID in @memID 
    AND msDurationType in @memType 
    AND msValidFrom >= @StartDate 
    AND msValidFrom < @EndDate (notice not <= end date which would include Dec 1) 

마침내 내 그룹 by. 당신은 msValidFrom에 의해 그것을 가지고 있지만 집계는 DISTINCT를하는 것처럼 (sum, min, max, avg) 수행되지 않으며, 만약 주어진 달에 대해 당신은 한 달 동안 모든 다른 날에 가입하는 사람들이있다 , 당신은 카운트와 함께 매일 있지만, 그것에 대해 매우 어려운 방법을 얻을 것이다. 나는

SELECT 
     datepart(yyyy, MS.msValidFrom) memberYear, 
     datepart(mm, MS.msValidFrom) memberMonth, 
     COUNT(*) as ActiveMembers 
    from 
     dbo.tblMembershipStatus MS 
    WHERE 
      MS.ms_memID = @memID 
     AND MS.msDurationType = @memType 
     AND MS.msValidFrom >= @StartDate 
     AND MS.msValidUntil < @EndDate 
    group by 
     datepart(yyyy, MS.msValidFrom), 
     datepart(mm, MS.msValidFrom) 

의 라인을 따라 뭔가를하고 제안 그러나 다시, 이것은 실제 테이블 구조, 샘플 데이터를 보지 않고있다,도 예상되는 욕망의 결과는 (당신이 원래의 게시물을 업데이트 제안. 정렬 탭을 사용하지 마십시오 , 공백을 누른 다음 Ctrl + K를 눌러 포맷을 차단하십시오.)