[server] SQL 데이터베이스 실제 파일 조각화

DBA로 고려해야 할 가지 종류의 조각화 가 실제로 있다는 것을 알고 있습니다.

  1. 인덱스 클러스터 된 인덱스 (테이블) 조각을 포함하여 SQL 데이터 파일의 단편화. DBCC SHOWCONTIG (SQL 2000) 또는 sys.dm_ db_ index_ physical_ stats (2005+)를 사용하여이를 식별하십시오.

  2. SQL 로그 파일 내에서 VLF 조각화 DBCC LOGINFO를 실행하여 각 SQL 로그 파일에 몇 개의 VLF가 있는지 확인하십시오.

  3. 하드 드라이브에있는 데이터베이스 파일의 실제 파일 조각화 Windows에서 “디스크 조각 모음”유틸리티를 사용하여이를 진단하십시오. ( 이 훌륭한 블로그 게시물에서 영감을 얻음 )

인덱스 조각화에 많은주의를 기울이고 있습니다 ( Paul Randall 의이 훌륭한 Serverfault 답변 참조 ). 제 질문의 초점이 아닙니다.

내가 할 수 알고 않도록 자주가 성장하고 정신과에서이 단편화가 가장 자주 발생하기 때문에, 합리적인 예상 데이터 파일 및 로그 크기를 계획하여 데이터베이스가 원래 생성 물리적 조각 (그리고 VLF 조각을),하지만 난 방법에 대한 몇 가지 질문이 수정 일단 식별되면 물리적 조각화 :

  • 우선, 물리적 조각화는 Enterprise SAN에서도 관련이 있습니까? SAN 드라이브에서 Windows 조각 모음을 사용해야합니까, 아니면 SAN 팀에서 내부 조각 모음 유틸리티를 사용해야합니까? SAN 드라이브에서 실행할 때 Windows 도구에서 얻은 조각화 분석도 정확 합니까?

  • SQL 성능에 대한 물리적 조각화는 얼마나 큰 문제입니까? (이전 질문의 결과를 보류하면서 내부 드라이브 배열을 가정 해 봅시다.) 내부 인덱스 조각화보다 더 큰 거래입니까? 아니면 실제로 같은 종류 의 문제입니까 (드라이브는 순차적 읽기 대신 임의 읽기를 수행해야합니다)

  • 드라이브가 물리적으로 조각화 된 경우 조각 모음 (또는 재구성) 색인이 시간 낭비입니까? 다른 문제를 해결하기 전에 문제를 해결해야합니까?

  • 프로덕션 SQL 상자에서 실제 파일 조각화를 해결하는 가장 좋은 방법은 무엇입니까? SQL 서비스를 끄고 Windows 조각 모음을 실행할 수 있다는 것도 알고 있지만 전체 백업을 수행하고 데이터베이스를 삭제 한 다음 백업에서 빈 드라이브로 복원하는 기술에 대해서도 들었습니다. 후자의 기술이 권장됩니까? 이 같은 백업에서 복원 하는가 도의 내부 인덱스 조각을 제거 처음부터 빌드 인덱스? 아니면 단순히 백업을 수행 할 때와 같은 순서로 페이지 순서를 반환합니까? (필요한 경우 압축을 통해 Quest Lightspeed 백업을 사용하고 있습니다.)

업데이트 : 지금까지 SAN 드라이브 조각 모음 (NO) 여부와 물리적 조각난 드라이브에서 인덱스 조각 모음이 여전히 가치가 있는지에 대한 좋은 답변 (YES).

다른 사람이 실제로 조각 모음을 수행하는 가장 좋은 방법에 대해 고민하고 있습니까? 또는 500GB 정도의 큰 조각난 드라이브를 조각 모음하는 데 걸리는 예상 시간은 얼마입니까? SQL 서버가 다운 될 때가 되었기 때문입니다.

또한 물리적 조각화를 수정하여 수행 한 SQL 성능 개선에 대한 일화 정보가있는 사람도 유용합니다. Mike의 블로그 게시물 은 문제를 발견하는 것에 대해 이야기하지만 어떤 종류의 개선에 대해서는 구체적이지 않습니다.



답변

이 기사에서는 SAN 드라이브 조각 모음에 대한 훌륭한 개요를 제공한다고 생각합니다.

http://www.las-solanas.com/storage_virtualization/san_volume_defragmentation.php

기본 요점은 LUN을 제시 할 때 SAN에 의해 ​​위치가 가상화 된 경우 디스크의 블록의 물리적 위치를 상호 연관시키기 어렵 기 때문에 SAN 스토리지에서 조각 모음이 권장되지 않는다는 것입니다.

RAW 장치 매핑을 사용 중이거나 작업중인 LUN 인 RAID 세트에 직접 액세스 할 수있는 경우 조각 모음이 긍정적 인 영향을 줄 수 있지만 공유 RAID에서 “가상”LUN이 제공되는 경우 5 개 세트


답변

이 질문과 답변의 여러 부분 :

Kevin이 지적했듯이 실제 파일 조각화는 Enterprise SAN 스토리지와 실제로 관련이 없으므로 추가 할 것은 없습니다. 실제로는 I / O 서브 시스템으로 이동하며 스캔을 수행 할 때 드라이브가 더 많은 I / O에서 스캔을 수행 할 때 더 순차적 인 I / O로 이동할 수있는 가능성이 있습니다. DAS의 경우 복잡한 슬라이스 앤 다이스 SAN의 경우에는 그렇지 않을 가능성이 큽니다.

파일 시스템 수준 조각 모음-SQL 종료시에만 수행하십시오. 온라인 데이터베이스 파일의 오픈 파일 조각 모음을 수행 한 적이 없기 때문에 여기에서 직접 문제가 발생하지는 않았지만 고객과 클라이언트로부터 이상한 부패 문제가 발생한다는 일화적인 증거를 많이 들었습니다. 일반적인 지혜는 SQL 온라인과 관련이 없습니다.

인덱스 조각화는 파일 조각화와 완전히 직교합니다. SQL Server는 파일 조각화에 대해 전혀 알지 못합니다. 실제 I / O 하위 시스템 지오메트리를 처리 할 수있을 정도로 너무 많은 가상화 계층이 있습니다. 그러나 인덱스 조각화는 SQL에 대한 모든 것을 알고 있습니다. 이미 언급 한 답변에서 나 자신을 너무 많이 반복하지 않으면 인덱스 조각화는 파일이 파일 시스템 수준에 어떻게 조각화되어 있는지에 관계없이 SQL이 효율적인 범위 스캔 판독을 수행하지 못하게합니다. 따라서 쿼리 성능이 저하되는 경우 인덱스 조각화를 반드시 완화해야합니다.

당신은하지 않습니다 이 파일 시스템 단편화 알아서하면되지만, 특정 순서로 다음을 수행하고 모든 인덱스를 다시 작성하고, 당신은 아마 갈거야 defragged 볼륨에 여러 파일을 성장하여 더 많은 파일 시스템 단편화의 원인 똑딱 거려 그래도 성능 문제가 발생합니까? 위에서 논의했듯이, 그것은 다음에 의존합니다 : -D

도움이 되었기를 바랍니다!


답변

프로덕션 SQL 상자에서 실제 파일 조각화를 해결하는 가장 좋은 방법은 무엇입니까?

데이터베이스 파일에서 SYSINTERNALS ‘contig를 실행합니다.

http://technet.microsoft.com/en-us/sysinternals/bb897428.aspx 참조


답변

db의 크기를 적절하게 조정하고 SQL 서버를 종료하고 데이터베이스 파일을 다른 디스크 배열에 복사 한 다음 다시 복사하여 조각 모음을 수행하는 것이 좋습니다. 내 경험에서 Windows 조각 모음을 사용하는 것보다 훨씬 빠릅니다.


답변

한 번 scsi 솔루션에서 물리 디스크 조각 모음을 시도했지만 성능이 거의 또는 전혀 향상되지 않았습니다. 내가 배운 교훈은 디스크 시스템으로 인해 성능이 저하되면 무작위 액세스를 사용하기 때문에 데이터 파일을 말하는 한 조각화와 관련이 없다는 것입니다.

인덱스가 조각 모음되고 통계가 업데이트되고 (매우 중요) 여전히 I / O가 병목 현상으로 나타나는 경우 물리적 조각화 이외의 다른 문제로 인해 어려움을 겪습니다. 드라이브의 80 % 이상을 사용 했습니까? 충분한 드라이브가 있습니까? 쿼리가 충분히 최적화 되었습니까? 클러스터 된 인덱스 조회가 뒤 따르는 많은 테이블 스캔 또는 더 많은 인덱스 탐색을 수행하고 있습니까? 쿼리 계획을보고 “통계 설정 io on”을 사용하여 쿼리에서 실제로 수행되는 작업을 찾으십시오. (많은 수의 논리적 또는 물리적 읽기를 찾으십시오)

내가 완전히 틀렸다면 알려주십시오.

하칸 윈터


답변

인덱스가 애플리케이션에 맞게 최적화되지 않았고 데이터베이스를 최적화 할 Veritas I3이없는 경우 다음과 같은 명령문을 사용하여 누락 된 인덱스를 찾을 수 있습니다.

       SELECT
      mid.statement,
      mid.equality_columns,
      mid.inequality_columns,
      mid.included_columns,
      migs.user_seeks,
      migs.user_scans,
      migs.last_user_seek,
      migs.avg_user_impact,
      user_scans,
      avg_total_user_cost,
      avg_total_user_cost * avg_user_impact * (user_seeks + user_scans) AS [weight]--, migs.*--, mid.*
   FROM
      sys.dm_db_missing_index_group_stats AS migs
      INNER JOIN sys.dm_db_missing_index_groups AS mig
         ON (migs.group_handle = mig.index_group_handle)
      INNER JOIN sys.dm_db_missing_index_details AS mid
         ON (mig.index_handle = mid.index_handle)
   ORDER BY
      avg_total_user_cost * avg_user_impact * (user_seeks + user_scans) DESC ;

또는 select 문에서 사용되지 않고 업데이트 / 삽입 성능을 저하시키는 인덱스를 찾기위한 다음과 같은 명령문 :

    CREATE PROCEDURE [ADMIN].[spIndexCostBenefit]
    @dbname [nvarchar](75)
WITH EXECUTE AS CALLER
AS
--set @dbname='Chess'
declare @dbid nvarchar(5)
declare @sql nvarchar(2000)
select @dbid = convert(nvarchar(5),db_id(@dbname))

set @sql=N'select ''object'' = t.name,i.name
        ,''user reads'' = iu.user_seeks + iu.user_scans + iu.user_lookups
        ,''system reads'' = iu.system_seeks + iu.system_scans + iu.system_lookups
        ,''user writes'' = iu.user_updates
        ,''system writes'' = iu.system_updates
from '+ @dbname + '.sys.dm_db_index_usage_stats iu
,' + @dbname + '.sys.indexes i
,' + @dbname + '.sys.tables t
where
    iu.database_id = ' + @dbid + '
and iu.index_id=i.index_id
and iu.object_id=i.object_id
and iu.object_id=t.object_id
AND (iu.user_seeks + iu.user_scans + iu.user_lookups)<iu.user_updates
order by ''user reads'' desc'

exec sp_executesql @sql

set @sql=N'SELECT
   ''object'' = t.name,
   o.index_id,
   ''usage_reads'' = user_seeks + user_scans + user_lookups,
   ''operational_reads'' = range_scan_count + singleton_lookup_count,
   range_scan_count,
   singleton_lookup_count,
   ''usage writes'' = user_updates,
   ''operational_leaf_writes'' = leaf_insert_count + leaf_update_count + leaf_delete_count,
   leaf_insert_count,
   leaf_update_count,
   leaf_delete_count,
   ''operational_leaf_page_splits'' = leaf_allocation_count,
   ''operational_nonleaf_writes'' = nonleaf_insert_count + nonleaf_update_count + nonleaf_delete_count,
   ''operational_nonleaf_page_splits'' = nonleaf_allocation_count
FROM
   ' + @dbname + '.sys.dm_db_index_operational_stats(' + @dbid + ', NULL, NULL, NULL) o,
   ' + @dbname + '.sys.dm_db_index_usage_stats u,
    ' + @dbname + '.sys.tables t
WHERE
   u.object_id = o.object_id
   AND u.index_id = o.index_id
    and u.object_id=t.object_id
ORDER BY
   operational_reads DESC,
   operational_leaf_writes,
   operational_nonleaf_writes'

exec sp_executesql @sql

GO

프로덕션 환경에서 성능 문제를 분석 할 때 사용하는 다른 SQL 문이 있지만이 두 가지가 좋은 시작입니다.

(이 게시물은 약간의 주제이지만 색인 전략과 관련이 있기 때문에 관심이있을 것이라고 생각했습니다.)

하칸 윈터


답변