Tất cả mọi thứ đều bằng nhau, nó phải đủ để nén cột đối tượng lớn (LOB) OriginalHTML
. Bạn không chỉ định tên chỉ mục được nhóm trong câu hỏi, vì vậy:
ALTER INDEX ALL
ON dbo.Articles
REORGANIZE
WITH (LOB_COMPACTION = ON);
Xem ALTER INDEX (Transact-SQL)
Nếu bạn có tên chỉ mục được nhóm (không chỉ (các) cột được phân cụm), hãy thay thế tên ALL
trên bằng tên đó.
Các LOB_COMPACTION
giá trị mặc định tùy chọn để ON
, nhưng không có thiệt hại trong việc rõ ràng. Bạn có thể cần phải chạy REORGANIZE
liên tục để hoàn tất việc lấy lại tất cả các không gian chưa sử dụng.
Thật không may, cách tổ chức dữ liệu LOB và cách triển khai nén LOB có nghĩa là phương pháp này có thể không phải lúc nào cũng có thể lấy lại tất cả không gian chưa sử dụng, bất kể bạn chạy nó bao nhiêu lần. Nó cũng có thể rất chậm.
Bạn cũng có thể thử phương thức trong Bảng Máy chủ SQL không gian không sử dụng miễn phí có liên quan
Nếu vì lý do nào đó, những điều trên không phù hợp với bạn, hãy xuất dữ liệu vào một tệp, cắt bớt bảng, sau đó tải lại . Có một số phương pháp để đạt được điều đó, ví dụ như tiện ích bcp .
Thí dụ
Sau đây tạo một bảng có 10.000 hàng rộng:
CREATE TABLE dbo.Test
(
c1 bigint IDENTITY NOT NULL,
c2 nvarchar(max) NOT NULL,
CONSTRAINT PK_dbo_Test
PRIMARY KEY CLUSTERED (c1)
);
-- Load 10,000 wide rows
INSERT dbo.Test WITH (TABLOCKX)
(c2)
SELECT TOP (10000)
REPLICATE(CONVERT(nvarchar(max), 'X'), 50000)
FROM master.sys.columns AS C1
CROSS JOIN master.sys.columns AS C2;
Chúng ta có thể thấy việc sử dụng không gian bằng sys.dm_db_index_physical_stats
DMV:
SELECT
DDIPS.index_id,
DDIPS.partition_number,
DDIPS.index_type_desc,
DDIPS.index_depth,
DDIPS.index_level,
DDIPS.page_count,
DDIPS.avg_page_space_used_in_percent
FROM sys.dm_db_index_physical_stats
(
DB_ID(),
OBJECT_ID(N'dbo.Test', N'U'),
1,
NULL,
'DETAILED'
) AS DDIPS
WHERE
DDIPS.alloc_unit_type_desc = N'LOB_DATA';
Bây giờ chúng tôi cập nhật nội dung LOB lên kích thước nhỏ hơn (nhưng vẫn yêu cầu lưu trữ ngoài hàng):
-- Change LOB data to a smaller value (that will not move in-row)
UPDATE dbo.Test WITH (TABLOCKX)
SET c2 = REPLICATE(CONVERT(nvarchar(max), 'Y'), 5000);
Lưu ý rằng một số không gian đã được thu hồi, nhưng các trang còn lại ít hơn nhiều so với trước đây.
Chúng tôi có thể nén không gian LOB bằng cách sử dụng:
ALTER INDEX PK_dbo_Test ON dbo.Test
REORGANIZE
WITH (LOB_COMPACTION = ON);
Điều này dẫn đến một số nén và tiết kiệm không gian, nhưng nó không hoàn hảo. Chạy lại nén có thể hoặc không thể cải thiện tình hình. Trong thử nghiệm của tôi, nó đã không, bất kể bao nhiêu lần tôi chạy lại nó.
Xuất, cắt, tải lại
Một cách để làm điều này hoàn toàn từ Management Studio liên quan đến việc sử dụng xp_cmdshell
để xuất dữ liệu bảng vào một tệp. Nếu xp_cmdshell
hiện không được bật, những điều sau đây sẽ làm điều đó:
-- Enable xp_cmdshell if necessary
EXECUTE sys.sp_configure
@configname = 'show advanced options',
@configvalue = 1;
RECONFIGURE;
EXECUTE sys.sp_configure
@configname = 'xp_cmdshell',
@configvalue = 1;
RECONFIGURE;
Bây giờ chúng ta có thể thực hiện xuất khẩu:
-- Export table
EXECUTE sys.xp_cmdshell
'bcp Sandpit.dbo.Test out c:\temp\Test.bcp -n -S .\SQL2017 -T';
Lưu ý bạn sẽ cần thay đổi đường dẫn và -S
tên máy chủ và có thể cung cấp thông tin đăng nhập.
Làm thế nào chúng ta có thể cắt bớt bảng và tải lại bằng cách sử dụng BULK INSERT
:
-- Truncate
TRUNCATE TABLE dbo.Test;
-- Switch to BULK_LOGGED recovery model if currently set to FULL
-- Bulk load
BULK INSERT dbo.Test
FROM 'c:\temp\Test.bcp'
WITH
(
DATAFILETYPE = 'widenative',
ORDER (c1),
TABLOCK,
KEEPIDENTITY
);
Bước cuối cùng là thiết lập lại hạt giống nhận dạng:
-- Check and reseed identity
DBCC CHECKIDENT('dbo.Test', RESEED);
Chuỗi hoạt động này thường nhanh hơn so với nén LOB và phải luôn tạo ra kết quả tối ưu:
Ở trên không hoàn toàn hiệu quả như có thể là do lỗi đã tồn tại từ lâu: BULK INSERT với cột IDENTITY tạo kế hoạch truy vấn với SORT . Cách giải quyết được liệt kê ở đó là hiệu quả, nhưng tôi sẽ chỉ bận tâm với nó nếu bảng rất lớn.
Đừng quên xóa tệp tạm thời được sử dụng để giữ dữ liệu đã xuất.
Tất nhiên bạn được tự do sử dụng bất kỳ cách tiếp cận xuất / nhập số lượng lớn nào thuận tiện nhất cho bạn. Nó không bắt buộc phải sử dụng xp_cmdshell
hoặc bcp
.
Ghi chú bổ sung:
FILLFACTOR
chỉ áp dụng cho các trang chỉ mục . Nó không ảnh hưởng đến lưu trữ LOB ngoài hàng (không được lưu trữ trên các trang chỉ mục).
- Nén hàng và trang không có sẵn để lưu trữ ngoài hàng.
Thay vào đó, bạn có thể nén và giải nén dữ liệu một cách rõ ràng bằng cách sử dụng COMPRESS
và các DECOMPRESS
chức năng có sẵn từ SQL Server 2016.
Tùy chọn cho những người sử dụng SQL Server 2014 (trường hợp ở đây) hoặc cũ hơn (xuống SQL Server 2005) để có cùng chức năng nén được cung cấp bởi các hàm COMPRESS
và DECOMPRESS
hàm tích hợp là sử dụng SQLCLR. Các hàm dựng sẵn chỉ thực hiện điều này có sẵn trong phiên bản SQL # miễn phí được viết bởi Solomon Rutzky . Các hàm Util_GZip và Util_GUnzip phải tương ứng với COMPRESS
và DECOMPRESS
, tương ứng. Và, bất cứ ai sử dụng SQL Server 2012 hoặc mới hơn nên đảm bảo rằng máy chủ đang chạy SQL Server được cập nhật với .NET Framework phiên bản 4.5 trở lên để thuật toán nén được cải thiện nhiều sẽ được sử dụng.
DATA_COMPRESSION
. Nén sẽ không nén dữ liệu được lưu trữ ngoài hàng, chẳng hạn như dữ liệu LOB hoặc dữ liệu ROW_OVERFLOW. Trong trường hợp này, chỉ các cột ID & URL sẽ nén - có thể không tiết kiệm đáng kể. Tuy nhiên, năm 2016 cũng giới thiệuCOMPRESS()
chức năng, cho phép OP sử dụng thuật toán gzip để nén dữ liệu OriginalHTML trong bảng.