Nỗ lực lấy lại không gian chưa sử dụng khiến không gian đã sử dụng tăng đáng kể trong SQL Server


15

Tôi có một bảng trong cơ sở dữ liệu sản xuất có kích thước 525 GB, trong đó 383 GB không được sử dụng:

Không gian chưa sử dụng

Tôi muốn lấy lại một số không gian này, nhưng, trước khi làm hỏng DB sản xuất, tôi đang thử nghiệm một số chiến lược trên một bảng giống hệt nhau trong một DB thử nghiệm với ít dữ liệu hơn. Bảng này có một vấn đề tương tự:

Không gian chưa sử dụng

Một số thông tin về bảng:

  • Hệ số lấp đầy được đặt thành 0
  • Có khoảng 30 cột
  • Một trong các cột là LOB loại hình ảnh và nó lưu trữ các tệp có kích thước từ vài KB đến vài trăm MB
  • Bảng không có bất kỳ chỉ mục giả định nào liên quan đến nó

Máy chủ đang chạy SQL Server 2017 (RTM-GDR) (KB4505224) - 14.0.2027.2 (X64). Cơ sở dữ liệu đang sử dụng SIMPLEmô hình phục hồi.

Một số điều tôi đã thử:

  • Xây dựng lại các chỉ mục : ALTER INDEX ALL ON dbo.MyTable REBUILD. Điều này đã có một tác động không đáng kể.
  • Sắp xếp lại các chỉ mục : ALTER INDEX ALL ON dbo.MyTable REORGANIZE WITH(LOB_COMPACTION = ON). Điều này đã có một tác động không đáng kể.
  • Sao chép cột LOB sang một bảng khác, bỏ cột, tạo lại cột và sao chép dữ liệu trở lại (như được nêu trong bài đăng này: Giải phóng Bảng máy chủ SQL không gian không sử dụng ). Điều này làm giảm không gian không sử dụng, nhưng dường như chỉ chuyển đổi nó thành không gian đã sử dụng:

    Không gian chưa sử dụng

  • Đã sử dụng tiện ích bcp để xuất bảng, cắt bớt nó và tải lại nó (như được nêu trong bài đăng này: Cách giải phóng không gian không sử dụng cho một bảng ). Điều này cũng làm giảm không gian không sử dụng và tăng không gian sử dụng đến một mức độ tương tự như hình ảnh trên.

  • Mặc dù điều đó không được khuyến khích, tôi đã thử các lệnh DBCC SHRINKFILE và DBCC SHRINKDATABASE, nhưng chúng không có bất kỳ tác động nào đến không gian không sử dụng.
  • Chạy DBCC CLEANTABLE('myDB', 'dbo.myTable')không làm nên sự khác biệt
  • Tôi đã thử tất cả các cách trên cả hai trong khi duy trì các kiểu dữ liệu hình ảnh và văn bản và sau khi thay đổi các kiểu dữ liệu thành varbinary (max) và varchar (max).
  • Tôi đã thử nhập dữ liệu vào một bảng mới trong cơ sở dữ liệu mới và điều này cũng chỉ chuyển đổi không gian chưa sử dụng thành không gian đã sử dụng. Tôi đã phác thảo chi tiết về nỗ lực này trong bài viết này .

Tôi không muốn thực hiện những nỗ lực này trên DB sản xuất nếu đây là những kết quả tôi có thể mong đợi, vì vậy:

  1. Tại sao không gian chưa sử dụng chỉ được chuyển đổi thành không gian đã sử dụng sau một số nỗ lực này? Tôi cảm thấy mình không hiểu rõ về những gì đang diễn ra dưới mui xe.
  2. Có cách nào khác tôi có thể làm để giảm không gian không sử dụng mà không tăng không gian sử dụng không?

EDIT: Đây là báo cáo và kịch bản sử dụng đĩa cho bảng:

Sử dụng đĩa

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MyTable](
    [Column1]  [int] NOT NULL,
    [Column2]  [int] NOT NULL,
    [Column3]  [int] NOT NULL,
    [Column4]  [bit] NOT NULL,
    [Column5]  [tinyint] NOT NULL,
    [Column6]  [datetime] NULL,
    [Column7]  [int] NOT NULL,
    [Column8]  [varchar](100) NULL,
    [Column9]  [varchar](256) NULL,
    [Column10] [int] NULL,
    [Column11] [image] NULL,
    [Column12] [text] NULL,
    [Column13] [varchar](100) NULL,
    [Column14] [varchar](6) NULL,
    [Column15] [int] NOT NULL,
    [Column16] [bit] NOT NULL,
    [Column17] [datetime] NULL,
    [Column18] [varchar](50) NULL,
    [Column19] [varchar](50) NULL,
    [Column20] [varchar](60) NULL,
    [Column21] [varchar](20) NULL,
    [Column22] [varchar](120) NULL,
    [Column23] [varchar](4) NULL,
    [Column24] [varchar](75) NULL,
    [Column25] [char](1) NULL,
    [Column26] [varchar](50) NULL,
    [Column27] [varchar](128) NULL,
    [Column28] [varchar](50) NULL,
    [Column29] [int] NULL,
    [Column30] [text] NULL,
 CONSTRAINT [PK] PRIMARY KEY CLUSTERED 
(
    [Column1] ASC,
    [Column2] ASC,
    [Column3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column4]  DEFAULT (0) FOR [Column4]
GO
ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column5]  DEFAULT (0) FOR [Column5]
GO
ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column15]  DEFAULT (0) FOR [Column15]
GO
ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column16]  DEFAULT (0) FOR [Column16]
GO

Dưới đây là kết quả thực hiện các lệnh trong câu trả lời của Max Vernon:

╔════════════╦═══════════╦════════════╦═════════════════╦══════════════════════╦════════════════════╗
 TotalBytes  FreeBytes  TotalPages  TotalEmptyPages  PageBytesFreePercent  UnusedPagesPercent 
╠════════════╬═══════════╬════════════╬═════════════════╬══════════════════════╬════════════════════╣
  9014280192 8653594624     1100376          997178             95.998700           90.621500 
╚════════════╩═══════════╩════════════╩═════════════════╩══════════════════════╩════════════════════╝
╔═════════════╦═══════════════════╦════════════════════╗
 ObjectName   ReservedPageCount       UsedPageCount 
╠═════════════╬═══════════════════╬════════════════════╣
 dbo.MyTable            5109090             2850245 
╚═════════════╩═══════════════════╩════════════════════╝

CẬP NHẬT:

Tôi đã chạy như sau theo đề xuất của Max Vernon:

DBCC UPDATEUSAGE (N'<database_name>', N'<table_name>');

Và đây là đầu ra:

DBCC UPDATEUSAGE: Usage counts updated for table 'MyTable' (index 'PK_MyTable', partition 1):
        USED pages (LOB Data): changed from (568025) to (1019641) pages.
        RSVD pages (LOB Data): changed from (1019761) to (1019763) pages.

Điều này cập nhật việc sử dụng đĩa cho bảng:

nhập mô tả hình ảnh ở đây

Và việc sử dụng đĩa tổng thể:

nhập mô tả hình ảnh ở đây

Vì vậy, có vẻ như vấn đề là việc sử dụng đĩa được theo dõi bởi SQL Server trở nên không đồng bộ với việc sử dụng đĩa thực tế. Tôi sẽ xem xét vấn đề này được giải quyết, nhưng tôi muốn biết tại sao điều này lại xảy ra ngay từ đầu!


Đã thu nhỏ thử sau khi thay đổi các loại dữ liệu?
LowlyDBA

1
Bất kỳ cơ hội nào bạn có thể chia sẻ repro bạn đã thực hiện với chúng tôi hoặc bạn chỉ đang sử dụng bản sao lưu cơ sở dữ liệu sản xuất của mình làm bản sao để kiểm tra?
John Eisbrener

@LowlyDBA Có, tôi đã thử thu nhỏ sau khi thay đổi loại dữ liệu.
Ken

Tôi đã chạy kịch bản và xác nhận rằng không có chỉ số giả định.
Ken

1
Đã bao lâu bạn có cơ sở dữ liệu này trong sản xuất? Bạn có thường xuyên chạy DBCC CHECKDBkhông? Bạn đã xem xét di chuyển ra khỏi các loại dữ liệu không dùng nữa , textimage? Họ có thể đang đóng góp cho các số liệu thống kê không phù hợp.
Max Vernon

Câu trả lời:


9

Tôi sẽ chạy DBCC UPDATEUSAGE trên bàn như bước đầu tiên, vì các triệu chứng cho thấy việc sử dụng không gian không nhất quán.

DBCC UPDATEUSAGE sửa các hàng, trang được sử dụng, trang dành riêng, trang lá và số trang dữ liệu cho mỗi phân vùng trong bảng hoặc chỉ mục. Nếu không có sự thiếu chính xác trong các bảng hệ thống, DBCC UPDATEUSAGE không trả về dữ liệu. Nếu không chính xác được tìm thấy và sửa chữa và VỚI NO_INFOMSGS không được sử dụng, DBCC UPDATEUSAGE trả về các hàng và cột được cập nhật trong bảng hệ thống.

Cú pháp là:

DBCC UPDATEUSAGE (N'<database_name>', N'<table_name>');

Sau khi bạn chạy nó, tôi sẽ chạy EXEC sys.sp_spaceusedlại bàn:

EXEC sys.sp_spaceused @objname = N'dbo.MyTable'
    , @updateusage = 'false' --true or false
    , @mode = 'ALL' --ALL, LOCAL_ONLY, REMOTE_ONLY
    , @oneresultset = 1;

Lệnh trên có tùy chọn để cập nhật việc sử dụng, nhưng vì bạn đã chạy DBCC UPDATEUSAGEthủ công trước, chỉ cần đặt nó thành false. Chạy DBCC UPDATEUSAGEthủ công cho phép bạn xem nếu có bất cứ điều gì đã được sửa chữa.

Truy vấn sau đây sẽ hiển thị phần trăm byte miễn phí trong bảng và tỷ lệ phần trăm các trang miễn phí trong bảng. Vì truy vấn sử dụng một tính năng không có giấy tờ, nên việc tính kết quả sẽ không khôn ngoan, nhưng có vẻ chính xác khi so sánh với đầu ra từ sys.sp_spaceused, ở mức cao.

Nếu phần trăm byte miễn phí cao hơn đáng kể so với phần trăm của các trang miễn phí, thì bạn có rất nhiều trang trống một phần.

Các trang trống một phần có thể xuất phát từ một số nguyên nhân, bao gồm:

  1. Chia tách trang, trong đó trang phải được phân chia để chứa các phần chèn mới vào chỉ mục được nhóm

  2. Không thể lấp đầy trang bằng các cột do kích thước cột.

Truy vấn sử dụng sys.dm_db_database_page_allocationschức năng quản lý động không có giấy tờ :

;WITH dpa AS 
(
    SELECT dpa.*
        , page_free_space_percent_corrected = 
          CASE COALESCE(dpa.page_type_desc, N'')
            WHEN N'TEXT_MIX_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
            WHEN N'TEXT_TREE_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
            ELSE COALESCE(dpa.page_free_space_percent, 100)
          END
    FROM sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID('dbo.MyTable'), NULL, NULL, 'DETAILED') dpa
)
, src AS
(
SELECT TotalKB = COUNT_BIG(1) * 8192 / 1024
    , FreeKB = SUM((dpa.page_free_space_percent_corrected / 100) * CONVERT(bigint, 8192)) / 1024
    , TotalPages = COUNT_BIG(1)
    , TotalEmptyPages = SUM(CASE WHEN dpa.page_free_space_percent_corrected = 100 THEN 1 ELSE 0 END) --completely empty pages
FROM dpa
)
SELECT *
    , BytesFreePercent = (CONVERT(decimal(38,2), src.FreeKB) / src.TotalKB) * 100
    , UnusedPagesPercent = (CONVERT(decimal(38,2), src.TotalEmptyPages) / src.TotalPages) * 100
FROM src

Đầu ra trông như:

╔═════════╦════════╦════════════╦═════════════════ ╦══════════════════╦════════════════════╗
TotalKB ║ FreeKB ║ TotalPages TotalEmptyPages BytesFreePercent Un usedPagesPercent
╠═════════╬════════╬════════════╬═════════════════ ╬══════════════════╬════════════════════╣
║ 208 96 ║ 26 12 46.153800 46.153800
╚═════════╩════════╩════════════╩═════════════════ ╩══════════════════╩════════════════════╝

Tôi đã viết một bài blog mô tả chức năng ở đây .

Trong kịch bản của bạn, vì bạn đã thực hiện ALTER TABLE ... REBUILD, bạn sẽ thấy một con số rất thấp TotalEmptyPages, nhưng tôi đoán bạn sẽ vẫn còn khoảng 72% BytesFreePercent.

Tôi đã sử dụng CREATE TABLEtập lệnh của bạn để cố gắng tạo lại kịch bản của bạn.

Đây là MCVE tôi đang sử dụng:

DROP TABLE IF EXISTS dbo.MyTable;

CREATE TABLE [dbo].[MyTable](
    [Column1]  [int]            NOT NULL IDENTITY(1,1),
    [Column2]  [int]            NOT NULL,
    [Column3]  [int]            NOT NULL,
    [Column4]  [bit]            NOT NULL,
    [Column5]  [tinyint]        NOT NULL,
    [Column6]  [datetime]       NULL,
    [Column7]  [int]            NOT NULL,
    [Column8]  [varchar](100)   NULL,
    [Column9]  [varchar](256)   NULL,
    [Column10] [int]            NULL,
    [Column11] [image]          NULL,
    [Column12] [text]           NULL,
    [Column13] [varchar](100)   NULL,
    [Column14] [varchar](6)     NULL,
    [Column15] [int]            NOT NULL,
    [Column16] [bit]            NOT NULL,
    [Column17] [datetime]       NULL,
    [Column18] [varchar](50)    NULL,
    [Column19] [varchar](50)    NULL,
    [Column20] [varchar](60)    NULL,
    [Column21] [varchar](20)    NULL,
    [Column22] [varchar](120)   NULL,
    [Column23] [varchar](4)     NULL,
    [Column24] [varchar](75)    NULL,
    [Column25] [char](1)        NULL,
    [Column26] [varchar](50)    NULL,
    [Column27] [varchar](128)   NULL,
    [Column28] [varchar](50)    NULL,
    [Column29] [int]            NULL,
    [Column30] [text]           NULL,
 CONSTRAINT [PK] PRIMARY KEY CLUSTERED 
(
    [Column1] ASC,
    [Column2] ASC,
    [Column3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column4]  DEFAULT (0) FOR [Column4]

ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column5]  DEFAULT (0) FOR [Column5]

ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column15]  DEFAULT (0) FOR [Column15]

ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column16]  DEFAULT (0) FOR [Column16]
GO

INSERT INTO dbo.MyTable (
      Column2
    , Column3
    , Column4
    , Column5
    , Column6
    , Column7
    , Column8
    , Column9
    , Column10
    , Column11
    , Column12
    , Column13
    , Column14
    , Column15
    , Column16
    , Column17
    , Column18
    , Column19
    , Column20
    , Column21
    , Column22
    , Column23
    , Column24
    , Column25
    , Column26
    , Column27
    , Column28
    , Column29
    , Column30
)
VALUES (
          0
        , 0
        , 0
        , 0
        , '2019-07-09 00:00:00'
        , 1
        , REPLICATE('A', 50)    
        , REPLICATE('B', 128)   
        , 0
        , REPLICATE(CONVERT(varchar(max), 'a'), 1)
        , REPLICATE(CONVERT(varchar(max), 'b'), 9000)
        , REPLICATE('C', 50)    
        , REPLICATE('D', 3)     
        , 0
        , 0
        , '2019-07-10 00:00:00'
        , REPLICATE('E', 25)    
        , REPLICATE('F', 25)    
        , REPLICATE('G', 30)    
        , REPLICATE('H', 10)    
        , REPLICATE('I', 120)   
        , REPLICATE('J', 4)     
        , REPLICATE('K', 75)    
        , 'L'       
        , REPLICATE('M', 50)    
        , REPLICATE('N', 128)   
        , REPLICATE('O', 50)    
        , 0
        , REPLICATE(CONVERT(varchar(max), 'c'), 90000)
);
--GO 100

;WITH dpa AS 
(
    SELECT dpa.*
        , page_free_space_percent_corrected = 
          CASE COALESCE(dpa.page_type_desc, N'')
            WHEN N'TEXT_MIX_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
            WHEN N'TEXT_TREE_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
            ELSE COALESCE(dpa.page_free_space_percent, 100)
          END
    FROM sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID('dbo.MyTable'), NULL, NULL, 'DETAILED') dpa
)
, src AS
(
SELECT TotalKB = COUNT_BIG(1) * 8192 / 1024
    , FreeKB = SUM((dpa.page_free_space_percent_corrected / 100) * CONVERT(bigint, 8192)) / 1024
    , TotalPages = COUNT_BIG(1)
    , TotalEmptyPages = SUM(CASE WHEN dpa.page_free_space_percent_corrected = 100 THEN 1 ELSE 0 END) --completely empty pages
FROM dpa
)
SELECT *
    , BytesFreePercent = (CONVERT(decimal(38,2), src.FreeKB) / src.TotalKB) * 100
    , UnusedPagesPercent = (CONVERT(decimal(38,2), src.TotalEmptyPages) / src.TotalPages) * 100
FROM src

Truy vấn sau đây hiển thị một dòng duy nhất cho mỗi trang được phân bổ cho bảng và sử dụng cùng DMV không có giấy tờ:

SELECT DatabaseName = d.name
    , ObjectName = o.name
    , IndexName = i.name
    , PartitionID = dpa.partition_id
    , dpa.allocation_unit_type_desc
    , dpa.allocated_page_file_id
    , dpa.allocated_page_page_id
    , dpa.is_allocated
    , dpa.page_free_space_percent --this seems unreliable
    , page_free_space_percent_corrected = 
        CASE COALESCE(dpa.page_type_desc, N'')
        WHEN N'TEXT_MIX_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
        WHEN N'TEXT_TREE_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
        ELSE COALESCE(dpa.page_free_space_percent, 100)
        END
    , dpa.page_type_desc
    , dpa.is_page_compressed
    , dpa.has_ghost_records
FROM sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID('dbo.MyTable'), NULL, NULL, 'DETAILED') dpa
    LEFT JOIN sys.databases d ON dpa.database_id = d.database_id
    LEFT JOIN sys.objects o ON dpa.object_id = o.object_id
    LEFT JOIN sys.indexes i ON dpa.object_id = i.object_id AND dpa.index_id = i.index_id
WHERE dpa.database_id = DB_ID() --sanity check for sys.objects and sys.indexes

Đầu ra sẽ hiển thị rất nhiều hàng nếu bạn chạy nó trên bảng thực trong môi trường thử nghiệm của bạn, nhưng nó có thể cho phép bạn xem vấn đề ở đâu.

Bạn có thể chạy đoạn script sau và đăng kết quả trong câu hỏi của bạn không? Tôi chỉ đang cố gắng đảm bảo chúng ta ở cùng một trang.

SELECT ObjectName = s.name + N'.' + o.name
    , ReservedPageCount = SUM(dps.reserved_page_count)
    , UsePageCount = SUM(dps.used_page_count)
FROM sys.schemas s
    INNER JOIN sys.objects o ON s.schema_id = o.schema_id
    INNER JOIN sys.partitions p ON o.object_id = p.object_id
    INNER JOIN sys.dm_db_partition_stats dps ON p.object_id = dps.object_id
WHERE s.name = N'dbo'
    AND o.name = N'MyTable'
GROUP BY s.name + N'.' + o.name;

2
Chạy DBCC UPDATEUSAGEcập nhật không gian chưa sử dụng và số trang không sử dụng. Có vẻ như việc sử dụng đĩa và thông tin trang được SQL Server báo cáo là không đồng bộ - Tôi đã cập nhật bài viết của mình với các chi tiết. Tôi tò mò về cách điều này sẽ xảy ra ở nơi đầu tiên, nhưng ít nhất vấn đề đã được tìm thấy. Cảm ơn tất cả sự giúp đỡ của bạn, tôi thực sự đánh giá cao nó!
Ken

0

Một trong các cột là LOB loại hình ảnh và nó lưu trữ các tệp có kích thước từ vài KB đến vài trăm MB

Bạn có thể gặp phải sự phân mảnh nội bộ.
Là gì phân mảnh trang cho bảng này?
Và sự phân mảnh cho các hàng liên tiếp có khác với các trang ngoài hàng không?

Bạn nói rằng bạn có các tệp là một vài KB.
SQL Server lưu trữ mọi thứ trong 8060 trang Byte. Có nghĩa là, nếu bạn có một hàng (hoặc dữ liệu ngoài hàng) là 4040 byte và dữ liệu tiếp theo tương tự nhau, nó không thể vừa cả hai trong cùng một trang và bạn sẽ lãng phí một nửa dung lượng của mình. Hãy thử thay đổi kích thước hàng của bạn bằng cách lưu trữ các cột có chiều dài thay đổi (ví dụ bắt đầu bằng hình ảnh) trong một bảng khác.


Tôi không nghĩ sự phân mảnh là vấn đề. Sau khi xây dựng lại các chỉ mục, sự phân mảnh cho chỉ mục được nhóm là 0,45% và độ đầy đủ của trang là 98,93%.
Ken

Việc xây dựng lại một bảng hoặc chỉ mục sẽ không giúp ích gì nếu bạn chịu đựng các hàng rất lớn hoặc dữ liệu LOB không phù hợp với các trang 8KB. Đó là những gì Max Vernon giải thích chi tiết hơn: "bạn có rất nhiều trang trống một phần." cũng được gọi là phân mảnh nội bộ
DrTrunks Bell

-3

Là cơ sở dữ liệu trong chế độ phục hồi đầy đủ? Nếu vậy, khi bạn thực hiện thu nhỏ, nó sẽ ghi lại tất cả các thay đổi và sẽ không thu nhỏ theo cách bạn mong đợi. Tùy thuộc vào giờ hoạt động của bạn, bạn có thể thực hiện sao lưu, chuyển sang chế độ khôi phục vận chuyển hàng loạt và sau đó chạy thu nhỏ trên tệp dữ liệu. Sau đó, bạn muốn chạy các tập lệnh chỉ mục để sửa chữa / xây dựng lại và chuyển trở lại phục hồi hoàn toàn. Đó là những gì tôi sẽ thử dù sao đi nữa, nó phụ thuộc vào số giờ hoạt động của bạn cho tất cả những điều này.


4
Đưa ra mô hình phục hồi là thú vị. Tôi nghĩ rằng nó sẽ được áp dụng nhiều hơn nếu OP gặp vấn đề với kích thước tệp nhật ký của họ . Vì hiện tại, họ đang gặp vấn đề với kích thước của tệp dữ liệu, vì vậy tôi rất ngạc nhiên nếu mô hình khôi phục gây ra sự cố được mô tả.
Josh Darnell

Đúng nhưng lần duy nhất tôi chạy co lại và nó không thực sự tác động đến không gian là do mô hình phục hồi nên tôi nghĩ rằng nó đáng để đưa lên trong trường hợp đó là chẩn đoán sai.
John-Henry Lochbaum

-3

Lần duy nhất tôi không thể thu nhỏ DB và lấy lại không gian là vì bạn không thể thu nhỏ DB vượt quá kích thước ban đầu của DB khi nó được tạo. Vì vậy, ví dụ, nếu DB của bạn là bản sao của DB sản xuất và lần đầu tiên bạn tạo DB ở mức 525GB, máy chủ sql sẽ không cho phép bạn thu nhỏ kích thước dưới 525GB cho dù bạn có xóa bao nhiêu dữ liệu từ DB. Nhưng nếu DB được tạo dưới 383GB và sau đó tăng lên thành 525GB, bạn sẽ không gặp khó khăn khi lấy lại dung lượng. Tôi từ lâu đã nghĩ rằng đây là một hạn chế ngu ngốc và tùy tiện của Microsoft.

Thu nhỏ cơ sở dữ liệu chỉ với kích thước ban đầu được đặt sau khi tạo cơ sở dữ liệu


Câu hỏi không phải là về việc thu hẹp cơ sở dữ liệu (và nếu có, khả năng thu nhỏ nó phụ thuộc vào không gian được sử dụng sau vùng kích thước ban đầu)
eckes

Miễn là có không gian chưa sử dụng, có thể thu nhỏ cơ sở dữ liệu thành một vài MB bất kể kích thước ban đầu. Nó không hẳn là một ý tưởng tốt nhưng tôi đã có nhiều lần thu nhỏ cơ sở dữ liệu và không bao giờ gặp phải giới hạn như thế này.
Ray

-3

Tôi đã gặp vấn đề này trước đây trên các hộp sản xuất, điều bạn cần làm là xây dựng lại các bảng và chỉ mục cho mỗi bảng (theo thứ tự đó).

Đây là truy vấn tôi sử dụng để kiểm tra các bảng. Nó sẽ giúp bạn xác định các bảng nào cần được xây dựng lại và tạo các truy vấn SQL bạn cần chạy. Truy vấn này được giới hạn ở những người có dung lượng không sử dụng lớn hơn 1 MB và tỷ lệ không sử dụng 5%, do đó bạn chỉ xây dựng lại những gì bạn thực sự cần tập trung vào:

SELECT  'alter table [' + t.NAME + '] rebuild;' AS SQL1, 'alter index all on [' + t.NAME + '] rebuild;' as SQL2, t.NAME AS TableName, p.rows AS RowCounts, SUM(a.total_pages) * 8/1024 AS TotalSpaceMB,  SUM(a.used_pages) * 8/1024 AS UsedSpaceMB,  (SUM(a.total_pages) - SUM(a.used_pages)) * 8/1024 AS UnusedSpaceMB, case when SUM(a.total_pages)=0 then 0 else (SUM(a.total_pages) - SUM(a.used_pages))*100/SUM(a.total_pages) end as Ratio  FROM     sys.tables t (nolock) INNER JOIN       sys.indexes i (nolock)  ON t.OBJECT_ID = i.object_id INNER JOIN  sys.partitions p (nolock) ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id INNER JOIN  sys.allocation_units a (nolock) ON p.partition_id = a.container_id LEFT OUTER JOIN  sys.schemas s (nolock) ON t.schema_id = s.schema_id WHERE  t.is_ms_shipped = 0 AND i.OBJECT_ID > 255  GROUP BY  t.Name, s.Name, p.Rows  
having  (SUM(a.total_pages) - SUM(a.used_pages)) * 8/1024>1
and (SUM(a.total_pages) - SUM(a.used_pages))*100/SUM(a.total_pages)>5
ORDER BY    5 desc

xây dựng lại bảng, như OP tuyên bố họ đã làm, sẽ loại bỏ hầu hết các phân mảnh. Tôi nghi ngờ làm một xây dựng lại sẽ giúp thêm.
Max Vernon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.