우리는 많은 수의 테이블이 생성되고 삭제되는 여러 데이터베이스를 가지고 있습니다. 우리가 알 수 있듯이 SQL Server는 시스템 기본 테이블 에 대한 내부 유지 관리를 수행하지 않으므로 시간이 지남에 따라 매우 조각화되고 크기가 커질 수 있습니다. 이는 버퍼 풀에 불필요한 압력을 가하고 데이터베이스의 모든 테이블 크기 계산과 같은 조작 성능에 부정적인 영향을 미칩니다.
이 핵심 내부 테이블에서 조각화를 최소화하기위한 제안이 있습니까? 한 가지 확실한 해결책은 너무 많은 테이블을 만들지 않거나 tempdb에 모든 임시 테이블을 만드는 것을 피할 수 있지만이 질문의 목적을 위해 응용 프로그램에 유연성이 없다고 가정 해 봅시다.
편집 : 추가 연구에 따르면이 답변되지 않은 질문 은 밀접하게 관련되어 있으며 수동 유지 관리의 일부 형식이 ALTER INDEX...REORGANIZE
옵션 일 수 있음을 나타냅니다 .
초기 연구
이 테이블에 대한 메타 데이터는 다음에서 볼 수 있습니다 sys.dm_db_partition_stats
.
-- The system base table that contains one row for every column in the system
SELECT row_count,
(reserved_page_count * 8 * 1024.0) / row_count AS bytes_per_row,
reserved_page_count/128. AS space_mb
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('sys.syscolpars')
AND index_id = 1
-- row_count: 15,600,859
-- bytes_per_row: 278.08
-- space_mb: 4,136
그러나 sys.dm_db_index_physical_stats
이러한 테이블의 조각화보기를 지원하지 않는 것 같습니다.
-- No fragmentation data is returned by sys.dm_db_index_physical_stats
SELECT *
FROM sys.dm_db_index_physical_stats(
DB_ID(),
OBJECT_ID('sys.syscolpars'),
NULL,
NULL,
'DETAILED'
)
Ola Hallengren의 스크립트 에는 is_ms_shipped = 1
객체의 조각 모음을 고려하는 매개 변수도 포함되어 있지만이 매개 변수를 활성화해도 시스템 기본 테이블은 자동으로 무시됩니다. 올라 (Ola)는 이것이 예상되는 행동이라고 설명했다. ms_shipped (예 :) 인 사용자 테이블 (시스템 테이블 아님 msdb.dbo.backupset
) 만 고려됩니다.
-- Returns code 0 (successful), but does not do any work for system base tables.
-- Instead of the expected commands to update statistics and reorganize indexes,
-- no commands are generated. The script seems to assume the target tables will
-- appear in sys.tables, but this does not appear to be a valid assumption for
-- system tables like sys.sysrowsets or sys.syscolpars.
DECLARE @result int;
EXEC @result = IndexOptimize @Databases = 'Test',
@FragmentationLow = 'INDEX_REORGANIZE',
@FragmentationMedium = 'INDEX_REORGANIZE',
@FragmentationHigh = 'INDEX_REORGANIZE',
@PageCountLevel = 0,
@UpdateStatistics = 'ALL',
@Indexes = '%Test.sys.sysrowsets.%',
-- Proc works properly if targeting a non-system table instead
--@Indexes = '%Test.dbo.Numbers.%',
@MSShippedObjects = 'Y',
@Execute = 'N';
PRINT(@result);
추가 요청 정보
inspect 시스템 테이블 버퍼 풀 사용 아래에서 Aaron의 쿼리를 적용하여 하나의 데이터베이스에 대한 버퍼 풀에 수십 GB의 시스템 테이블이 있으며 그 경우 공간의 ~ 80 %가 여유 공간이라는 것을 알았습니다. .
-- Compute buffer pool usage by system table
SELECT OBJECT_NAME(p.object_id),
COUNT(b.page_id) pages,
SUM(b.free_space_in_bytes/8192.0) free_pages
FROM sys.dm_os_buffer_descriptors b
JOIN sys.allocation_units a
ON a.allocation_unit_id = b.allocation_unit_id
JOIN sys.partitions p
ON p.partition_id = a.container_id
AND p.object_id < 1000 -- A loose proxy for system tables
WHERE b.database_id = DB_ID()
GROUP BY p.object_id
ORDER BY pages DESC