Có cách nào để thay đổi kiểu dữ liệu cột dưới dạng hoạt động chỉ siêu dữ liệu không?
Tôi không nghĩ vậy, đây là cách sản phẩm hoạt động ngay bây giờ. Có một số cách giải quyết thực sự tuyệt vời cho giới hạn này được đề xuất trong câu trả lời của Joe .
... kết quả là SQL Server viết lại toàn bộ bảng (và sử dụng kích thước bảng 2x trong không gian nhật ký)
Tôi sẽ trả lời riêng hai phần của tuyên bố đó.
Viết lại bảng
Như tôi đã đề cập trước đây, thực sự không có cách nào để tránh điều này. Đó dường như là thực tế của tình huống, ngay cả khi nó không có ý nghĩa hoàn toàn từ quan điểm của chúng tôi là khách hàng.
Nhìn vào DBCC PAGE
trước và sau khi thay đổi cột từ 4000 thành 260 cho thấy tất cả dữ liệu được sao chép trên trang dữ liệu (bảng thử nghiệm của tôi có 'A'
260 lần liên tiếp):
Tại thời điểm này, có hai bản sao của cùng một dữ liệu trên trang. Cột "cũ" về cơ bản đã bị xóa (id được thay đổi từ id = 2 thành id = 67108865) và phiên bản "mới" của cột được cập nhật để trỏ đến phần bù mới của dữ liệu trên trang:
Sử dụng kích thước bảng 2x trong không gian nhật ký
Thêm WITH (ONLINE = ON)
vào cuối ALTER
câu lệnh làm giảm khoảng một nửa hoạt động ghi nhật ký , vì vậy đây là một cải tiến bạn có thể thực hiện để giảm lượng ghi vào không gian đĩa / đĩa cần thiết.
Tôi đã sử dụng khai thác thử nghiệm này để thử nó:
USE [master];
GO
DROP DATABASE IF EXISTS [248749];
GO
CREATE DATABASE [248749]
ON PRIMARY
(
NAME = N'248749',
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.SQL2017\MSSQL\DATA\248749.mdf',
SIZE = 2048000KB,
FILEGROWTH = 65536KB
)
LOG ON
(
NAME = N'248749_log',
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.SQL2017\MSSQL\DATA\248749_log.ldf',
SIZE = 2048000KB,
FILEGROWTH = 65536KB
);
GO
USE [248749];
GO
CREATE TABLE dbo.[table]
(
id int IDENTITY(1,1) NOT NULL,
[col] nvarchar (4000) NULL,
CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED (id ASC)
);
INSERT INTO dbo.[table]
SELECT TOP (1000000)
REPLICATE(N'A', 260)
FROM master.dbo.spt_values v1
CROSS JOIN master.dbo.spt_values v2
CROSS JOIN master.dbo.spt_values v3;
GO
Tôi đã kiểm tra sys.dm_io_virtual_file_stats(DB_ID(N'248749'), DEFAULT)
trước và sau khi chạy ALTER
câu lệnh, và đây là sự khác biệt:
Mặc định (Ngoại tuyến) ALTER
- Tệp dữ liệu ghi / byte được ghi: 34,809 / 2,193,801,216
- Nhật ký tệp ghi / byte được viết: 40.953 / 1.484.910.080
Trực tuyến ALTER
- Tệp dữ liệu ghi / byte được ghi: 36.874 / 1.693.745.152 (giảm 22,8%)
- Tệp nhật ký ghi / byte được ghi: 24.680 / 866.166.272 (giảm 41%)
Như bạn có thể thấy, có một sự sụt giảm nhẹ trong việc ghi tệp dữ liệu và sự sụt giảm lớn trong tệp nhật ký ghi.