9

가능한 설명에서 예기치 않은 속도 저하는 SQL 서버 2014 엔터프라이즈 에디션 (64 비트)에서 여기 in the commentSQL Server 쿼리 최적화 - 간단한 쿼리

입니다 - 내가보기에서 읽으려고하고있다. 표준 쿼리에는 이와 같이 ORDER BYOFFSET-FETCH 절만 포함됩니다. 동일한 결과를 반환 다음 쿼리보다 (150K 같은 행 다수 스킵 할 때 눈에 띄는) 1

SELECT 

    * 

FROM Metadata 
ORDER BY 
    AgeInHours  ASC, 
    RankingPoint DESC, 
    PublishDate  DESC 
OFFSET 150000 ROWS 
FETCH NEXT 40 ROWS ONLY 

접근법 그러나 이러한 비교적 간단한 쿼리 거의 9 배 느리게 행한다. I는 판독하고이 경우

주 사용 후 첫번째 키와 해당 WHERE...IN 함수에 대한 파라미터로서

접근법 2

SELECT 
    * 
FROM Metadata 
WHERE NewsId IN (
    SELECT 

     NewsId 

    FROM Metadata 
    ORDER BY 
     AgeInHours  ASC, 
     RankingPoint DESC, 
     PublishDate  DESC 
    OFFSET 150000 ROWS 
    FETCH NEXT 40 ROWS ONLY 
) 
ORDER BY 
    AgeInHours  ASC, 
    RankingPoint DESC, 
    PublishDate  DESC 

벤치마킹 차이

두 쇼
(40 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 14748 ms, elapsed time = 3329 ms. 

(40 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 3828 ms, elapsed time = 469 ms. 

기본 키에 대한 색인이 PubilshDate이고 그 fragmentat가 있습니다. 이온이 매우 낮습니다. 또한 데이터베이스 테이블에 대해 유사한 쿼리를 실행하려고 시도했지만 모든 경우에 두 번째 방법은 성능이 크게 향상되었습니다. SQL Server 2012에서도이 기능을 테스트했습니다.

어떤 일이 벌어지고 있는지 설명 할 수 있습니까?

스키마

Schema

접근 1 : 실행 계획

Approach 1: Execution Plan

접근법 2 : 실행 계획 (왼쪽 부분)

Approach 2: Execution Plan (Left part)

접근법 2 : 실행 계획 (오른쪽 부분)

Approach 2: Execution Plan (Right part)

+0

첫 번째 접근 방식을 실행하고 ** ** ID' 열만 선택하면 어떻게됩니까? 나는'*'별표가 전체 컬럼을 스캔하도록 강제하기 때문에 별표가 쿼리 속도를 늦춘 것으로 의심된다. – sagi

+0

인덱싱 된 열 ('Id') 만 찾는 것보다 훨씬 빠릅니다 (거의 9 번 말합니다). 수수께끼 같은 점은 두 번째 쿼리에서'WHERE-IN' 절을 사용할 때 여전히 같은 양의 데이터를 읽는 중입니다.하지만 시간이 걸리지는 않습니다. 현장 뒤에 무슨 일이 일어나고있는거야? – undefined

+3

쿼리 계획과 테이블 스키마를 포함 할 수 있습니까? –

답변

0

당신은 엔진이 최적의 성능을 얻기 위해 사용될 수있는 인덱스에 대한 조회 쿼리를 실행할 때 . 귀하의 접근 방식 1은 SELECT 문에서 모든 열을 포함하지 않는 색인을 사용하고 있습니다. 이것은 쿼리 계획에서 주요 조회를 발생시킵니다. 내 경험상 SELECT 문에서 색인 된 열만 사용하는 성능이 항상 떨어집니다.

AgeInHours, RankingPoint, PublishDate에 대한 색인을 만들고 모든 열을 INCLUDE하면 (테스트 목적으로 만 권장 됨) 차이점을 확인할 수 있습니다.

CTE를 사용하고 IN을 사용하여 WHERE 대신 JOIN을 만들거나 수백만 개의 행이있는 경우 인덱스가있는 임시 테이블을 만드는 경우 두 번째 방법을 사용하면 더 나은 성능을 얻을 수도 있습니다.

1

동일한 결과 집합을 사용하여 다르게 구조화 된 쿼리의 경우 서로 다른 쿼리 및 쿼리 비용으로 다른 쿼리 계획을 얻습니다. 이는 다양한 SQL RDBMS 구현에 공통적입니다.

큰 테이블에서 데이터의 작은 부분을 선택할 때 위의 샘플에서는 기본적으로 결과에서 행 수를 줄이거 나 최소화 한 다음 모든 쿼리 열과 함께 전체 행을 선택하는 것이 좋습니다.

또 다른 접근법은 첫 번째 단계에서 결과 집합을 줄이기위한 정확한 적절한 색인을 작성하는 것입니다. 위의 쿼리에서 아마도 같은 열과 정렬 순서로 된 ORDER BY 절의 열이 해결책이 될 수 있습니다.

는 (당신은 그냥 자신의 이름 뒤에 숨겨져 있는지 상상할 수있는 쿼리 계획에서 언급 된 인덱스의 구조를 전송하지 않았다.)

당신은 또한 당신이 고려해야 특정 인덱스에 SQL 최적화를 직접 암시 SQL 인덱스를 사용할 수 있습니다 SQL 최적화 프로그램이 작업을 수행하지 않는 경우 작업에 가장 적합합니다.