2009-11-11 8 views
18

내 테이블 (SQL Server 2008)에 100 만 개 이상의 레코드가 있고 datetime으로 레코드를 정렬하려고하면 1 초가 걸리지 만 ID (int)로 정렬하면 0.1 초 정도 걸립니다.SQL Server 2008 : 날짜 시간별 정렬이 너무 느림

효율성을 향상시킬 방법이 있습니까? (이미 날짜 시간 열을 인덱스에 추가했습니다.)

+0

어떤 RDBMS를 사용하고 있습니까? – Quassnoi

+0

SQL Server 2008 – silent

+7

은 자체 datetime 열의 별도 인덱스에 있습니까? 당신은 "추가 된 .. 색인에 ...."....날짜 시간 열이 예 : 칼럼 번호. 3 복합 인덱스에서 그 datetime 열만으로 주문하려고하면 전혀 도움이되지 않습니다 ........ –

답변

23

id의 정렬은 클러스터 된 인덱스 검색을 사용하는 반면은 정렬 또는 인덱스 조회를 사용합니다.

이 두 가지 방법 모두 클러스터형 인덱스 스캔보다 느립니다.

표가 클러스터 된 경우 id은 기본적으로 이미 정렬되었음을 나타냅니다. 레코드는 B+Tree에 포함되어 있으며 페이지는 id 순서로 링크 된 연결된 목록이 있습니다. 엔진은 연결된 목록을 트래버스하여 id에 의해 정렬 된 레코드를 가져와야합니다.

id을 순차적으로 삽입 한 경우 행의 실제 순서가 논리적 순서와 일치하며 클러스터형 인덱스 검사가 더 빠를 것입니다.

  • 는 테이블에서 모든 기록을 가지고 그들을 분류 :

    당신이 당신의 기록이 datetime으로 주문하려면

    은 두 가지 옵션이 있습니다. 천천히 느껴진다.
  • datetime에 색인을 사용하십시오. 인덱스는 디스크의 별도 공간에 저장됩니다. 즉, 엔진은 중첩 루프의 인덱스 페이지와 테이블 페이지 사이를 셔틀해야합니다. 그것은 너무 느립니다.

    CREATE INDEX ix_mytable_datetime ON mytable (datetime) INCLUDE (field1, field2, …) 
    

    을, 당신은 그 인덱스로 쿼리에서 사용하는 모든 열을 포함 :

datetime에 별도의 커버 인덱스를 만들 수 있습니다, 주문을 향상시킬 수 있도록 지원합니다.

이 인덱스는 테이블의 섀도 복사본과 비슷하지만 순서가 다른 데이터 정렬 방식입니다.

이렇게하면 id의 순서대로 datetime만큼 빠르게 정렬 할 수 있습니다 (색인에 모든 데이터가 포함되어 있으므로) 키 조회를 제거 할 수 있습니다.

업데이트 :

이 문제에 신선한 블로그 게시물 :

+0

이렇게하는 효율적인 방법이 있습니까? – silent

+0

나는 데이터베이스가이 형식으로 어쨌든 저장 될 것이라고 믿는다. 처음에는 똑같은 생각이 들었지만 대답이되어야한다고 생각하지 않습니다. – Jrud

+1

+1 datetime 정렬을 위해 최적화하려면 datetime을 클러스터 된 인덱스로 만들고 id 인덱스를 클러스터되지 않은 기본 키로 만듭니다. – Andomar

0

당신은 int로서 datatime를 저장하지만 때마다 변환 시간이 걸릴 것 어쩌면 경우 저장 또는 데이터 가져 오기. (IP 주소와 같은 직원을 저장하는 데 일반적으로 사용되는 기술로 빠른 검색 시간이 필요함)

서버에서 datetime을 저장하는 방법을 확인해야합니다. 서버가 이미 int 또는 bigint로 저장합니다. 아무것도 바꿀 수 없다 ....

2

새 색인에 날짜 시간을 추가하고이 색인에 ID를 추가하면 여전히 도움이되지 않습니다.

0

datetime 필드에 많은 고유 값이 포함되어 있고 그 값이 거의 변경되지 않으면 datetime 필드에 클러스터 된 인덱스를 정의하십시오. 그러면 실제 데이터가 datetime 값으로 정렬됩니다. 클러스터형 인덱스 사용에 대해서는 http://msdn.microsoft.com/en-us/library/aa933131(SQL.80).aspx을 참조하십시오.

이렇게하면 클러스터되지 않은 색인을 사용하도록 강요되므로 int 검색을 더 느리게 만들 수 있습니다.

1

int 열에 대한 인덱스가 있지만 datetime 열에 대한 인덱스가있을 수 있습니까? 실행 계획을 살펴보십시오.

+0

+1 좋은 포인트 - 실행 계획을 확인하십시오! 색인이 전혀 사용되고 있지 않습니까 ?? –

0

"the"인덱스 또는 독점 인덱스에 DateTime 필드를 추가 했습니까? 다른 필드와 DateTime 또는이 필드 만 선택을 필터링합니까?

성능을 최적화하기 위해 필터링하는 모든 필드가있는 인덱스가 있어야하며, 동일한 순서로 인덱스가 있어야합니다.

  • 이 두 번째 순서는
  • 종류의

첫 번째 옵션은 빠른 행을 요구 제공하는 인덱스를 사용하여 행을 스캔 :

+0

기존 색인에 추가 했으므로 방금 새 색인을 만들려고했지만 비교적 빨리 (0.5 초) 표시되지만 int 열보다 느립니다. – silent

+0

"WHERE"및 "ORDER BY"문 (및 "GROUP BY"가있는 경우)의 필드를 확인하는 것이 중요합니다. 동일한 필드 및 동일한 순서 여야합니다. 표의 모든 열이 필요하지 않은 경우 원하는 필드 만 사용하여 선택하십시오. 그런 다음 캐시 및 통계를 지우고 결과를 시도하십시오. 또한 많은 양의 데이터가있는 테이블에서 클러스터 된 인덱스와 동일한 속도로 선택하는 것이 어렵다고 생각합니다. 이것은 클러스터 된 클러스터를 신중하게 선택해야하는 이유입니다. –

6

엔진에 의해 순서를 존중하려면 두 가지 대안이있다 천천히. 문제는 인덱스를 사용하기 위해서는 인덱스가 인 이어야한다는 것입니다. 이것은 SELECT 투영 목록의 모든 열과 WHERE 절에 사용 된 모든 열을 포함한다는 것을 의미합니다 (최소). 인덱스가 포함되지 않으면 엔진은 필요한 열의 값을 검색하기 위해 각 행에 대해 클러스터 된 인덱스 (예 : '테이블')를 조회해야합니다. 이 상수 값 조회는 비용이 많이 들며, 엔진이 클러스터 된 인덱스를 스캔하고 결과를 정렬하는 것이 더 효율적일 때 (정당하게) 클러스터링되지 않은 인덱스는 사실상 무시됩니다. 자세한 내용은 The Tipping Point Query Answers을 참조하십시오.

는 다음과 같은 세 가지 쿼리를 고려 : 첫 번째는 dateColumn에 클러스터되지 않은 인덱스를 사용한다

SELECT dateColumn FROM table ORDER BY dateColumn 
SELECT * FROM table ORDER BY dateColumn 
SELECT someColumn FROM table ORDER BY dateColumn 

. 하지만 두 번째 것은 dateColumn에 대한 색인을 사용하지 않을 것이고 대신 1M 행에 대해 검색 및 정렬을 선택합니다. 반면에 세 번째 쿼리는 Table(dateColumn) INCLUDE (someColumn)에 대한 인덱스로부터 이점을 얻을 수 있습니다. Index Design Basics, General Index Design Guidelines, Nonclustered Index Design Guidelines 또는 How To: Optimize SQL Indexes를 참조

이 항목은 MSDN에 대규모로 덮여있다.

궁극적으로 테이블 디자인의 가장 중요한 선택은 사용하는 클러스터 된 인덱스입니다. 거의 항상 기본 키 (일반적으로 자동 증가 ID)는 특정 OLTP로드에만 유익한 결정 인 클러스터 된 인덱스로 유지됩니다.

마지막으로 확실한 질문입니다. 왜 세계에서 1 백만 행을 주문 하시겠습니까 ?? 너는 그걸 전시 할 수 없지, 그렇지? 귀하의 유스 케이스에 대해 조금 더 설명하면보다 나은 답변을 찾을 수 있습니다.

+0

Remus, 한 번에 1 백만 + 레코드를 표시하고 싶지 않습니다. 페이징에 row_number() 메서드를 사용하고 있지만 페이지 번호 50000 (20 rec/page)과 같이 큰 숫자를 탐색하려고하면 발견되었습니다.), 질의는 매우 느려지지만 주문 방법을 ID로 변경하면 거의 10 배 더 빠릅니다. – silent

+1

row_number 페이지 매김이어야한다고 생각했습니다. 혹시 LINQ입니까? 가장 좋은 방법은 쿼리를 다음과 같이 표현하는 것입니다. 원하는 페이지의 ID를 선택하고 (17 페이지의 20 개의 ID) 20 개의 레코드 세부 정보를 검색합니다. 이것은 T-SQL과 LINQ로 표현할 수 있으며 충분히 빠를 수 있습니다. 스키마와 쿼리를 게시하는 것이 좋습니다. –