모든 것을 다시 작성하고 색인을 생성 한 후에도 왜 여전히 데이터베이스가 조각화됩니까?


40

이 T-SQL을 실행하여 모든 테이블을 한 번에 조각 모음하려고하는 데이터베이스가 있습니다.

SELECT 
        'ALTER INDEX all ON ' + name + ' REORGANIZE;' + CHAR(10) +
        'ALTER INDEX all ON ' + name + ' REBUILD;'
    FROM sys.tables

그런 다음 출력을 복사하여 새 쿼리 창에 붙여 넣고 실행합니다. 오류가 없지만 여전히 조각화가 있습니다. 두 명령을 별도로 실행하려고 시도했지만 여전히 조각화가 있습니다. 참고 :REORGANIZE Aaron이 필요하지 않다는 것을 알고 있으며 동적 SQL을 사용하여이를 자동화 할 수 있다는 것을 알고 있습니다.

나는 여전히 조각화가 있다고 판단하기 위해 이것을 실행했다.

SELECT * FROM 
sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, NULL) 
WHERE avg_fragmentation_in_percent > 0

그리고 나는 얻었다 :

database_id object_id   index_id    partition_number    index_type_desc alloc_unit_type_desc    index_depth index_level avg_fragmentation_in_percent    fragment_count  avg_fragment_size_in_pages  page_count  avg_page_space_used_in_percent  record_count    ghost_record_count  version_ghost_record_count  min_record_size_in_bytes    max_record_size_in_bytes    avg_record_size_in_bytes    forwarded_record_count  compressed_page_count
85  171147655   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   36.3636363636364    5   2.2 11  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  421576540   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   75  7   1.14285714285714    8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  965578478   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   14.7058823529412    6   5.66666666666667    34  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1061578820  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   40  4   1.25    5   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1109578991  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   30.7692307692308    5   2.6 13  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1205579333  2   1   NONCLUSTERED INDEX  IN_ROW_DATA 2   0   50  5   1.6 8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1493580359  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   50  6   1.66666666666667    10  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

나는 진짜 기초가 빠져 있다는 것을 알고 있지만, 무엇을 모른다.


어떤 오류가 발생 했습니까? 또한 동일한 것을 재구성하고 재구성 해야하는 이유가 있습니까?
Shawn Melton

숀, 한 마디도 없어서 죄송합니다. 오류 가 없습니다 . 두 명령을 모두 실행 한 이유는 각 명령을 개별적으로 시도한 후에 수행했습니다. 질문을 업데이트했습니다.
저스틴 친애하는

답변:


38

테이블이 작습니다. 표의 페이지 수는 다음과 같습니다.

11, 8, 6, 5, 13, 8, 10

총 480kb를 차지합니다. 말 그대로 조각 모음 할 것이 없습니다.

편집 : 이것은 약간의 설명이 필요합니다.

새로운 테이블이나 인덱스는 일반적으로 균일 한 범위가 아닌 혼합 된 것에서 처음 8 페이지입니다. 따라서 처음 8 개의 페이지 각각을 서로 다른 혼합 범위에서 할당 할 수 있습니다. 따라서 8 페이지를 소비하는 테이블 또는 인덱스는 8 개의 서로 다른 혼합 범위마다 1 개씩 8 개의 조각을 가질 수 있습니다.

보다 널리 사용되는 조각 모음 스크립트 (아래에 링크 된 몇 가지 예)는이 때문에 작은 테이블을 제외하는 경향이 있습니다. IIRC, <500 페이지는 둘 중 하나 또는 둘 다에 있습니다. 이러한 크기에서는 조각 모음에 대한 이점이 거의 없으며 조각화 된 수치는 혼합 범위 할당에 의해 잠재적으로 왜곡 될 수 있습니다.


다른 사람이 더 나은 답변을 얻지 않으면 만족할 것입니다.
저스틴

3
+1 마크와 동의 함. 실제로 일부 데이터가있을 때 조각화에 대해 걱정하십시오. :-)
Aaron Bertrand

나는 당신이 말하는 것을 완전히 이해합니다. 그러나 db 엔진이 그러한 페이지를 조각 모음 할 수 없기 때문에 호기심이 많습니까? 나는 이것에 대한 이유가 있어야 함을 의미합니다.
토마스 스트링거

3
그것은 할 수 없다는 것이 아니라 왜 귀찮게합니까? 그렇게하면 I / O에 거의 영향을 미치지 않습니다. 특히이 작은 테이블은 어쨌든 거의 메모리에 있다는 것이 보장되기 때문입니다.
Aaron Bertrand

1
다만. 이상해 보인다. 인덱스 조각화를 확인하고보고하는 응용 프로그램을 작성한다고 가정하면 조각 비율을 테스트 할뿐만 아니라 잘못된 알람이 없도록 페이지 수를 추가하는 논리를 추가해야한다고 가정 해보십시오.
토마스 스트링거

18

" Microsoft SQL Server 2000 인덱스 조각 모음 모범 사례 " 에서 인용하십시오 .

"조각화는 디스크 I / O에 영향을 미칩니다. 따라서 SQL Server에서 페이지를 캐시 할 가능성이 적으므로 더 큰 인덱스에 집중하십시오. DBCC SHOWCONTIG가보고 한 페이지 수를 사용하여 인덱스 크기에 대한 아이디어를 얻으십시오 (각 페이지는 크기가 8KB 인 경우) 일반적으로 1,000 페이지 미만의 인덱스 조각화 수준에 대해서는 신경 쓰지 말아야합니다 . 만약 테스트에서 10,000 페이지를 초과하는 인덱스는 성능이 향상되었으며 페이지 수가 많은 인덱스가 가장 크게 향상되었습니다. 50,000 페이지 이상) . "

따라서 이런 종류의 질문에 답하고 Mark와 Aaron의 대답을 뒷받침합니다.

Brent Ozar의 다음 기사에서 인덱스 조각화에 대한 좋은 정보를 찾을 수 있습니다.

(또한 단편화 문제에 대한) 일반적으로 인덱스에 대한 좋은 정보의 Also..an 바다가에서 찾을 수 있습니다 킴벌리 트립의 블로그 .


11

이것은 귀하의 질문에 대답하기위한 것이 아니라, 의견에 결코 맞지 않을 것입니다. 출력을 다른 창에 복사하여 붙여 넣지 않고도이 스크립트를 동적으로 빌드 할 수 있습니다. 고려하는 것은 절대적 이유가 없다는 것을 REORGANIZE다음과 REBUILD:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER INDEX all ON ' + name + ' REBUILD;
    ' FROM sys.tables;

PRINT @sql; -- to see the first 8,000 characters and make sure it checks out
-- EXEC sp_executesql @sql;

Aaron, 동적 SQL을 지적 해 주셔서 감사합니다. 동적 SQL을 잘 알고 있습니다. 솔루션이 작동 할 때까지 솔루션을 자동화하지는 않았습니다. 이것을 읽는 다른 사람들은 아마 알고 있어야합니다.
저스틴 친애하는
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.