列のデータ型をメタデータのみの操作として変更する方法はありますか?
私はそうは思わない、これが今の製品の仕組みだ。Joeの回答で提案されたこの制限に対するいくつかの本当に素晴らしい回避策があります。
...結果として、SQL Serverはテーブル全体を書き換えます(ログ領域で2倍のテーブルサイズを使用します)
その声明の2つの部分に個別に対応します。
テーブルの書き換え
前述したように、これを回避する方法はありません。顧客としての私たちの観点から完全に意味をなさない場合でも、それは状況の現実のようです。
DBCC PAGE
列を4000から260に変更する前後を見ると、すべてのデータがデータページに複製されていることがわかります(私のテストテーブル'A'
の行数は260回でした)。
この時点で、ページにはまったく同じデータの2つのコピーがあります。「古い」列は基本的に削除され(idはid = 2からid = 67108865に変更されます)、ページのデータの新しいオフセットを指すように「新しい」バージョンの列が更新されます。
ログスペースで2倍のテーブルサイズを使用する
ステートメントWITH (ONLINE = ON)
の最後に追加すると、ロギングアクティビティが約半分に削減されるため、これは必要なディスク/ディスク領域への書き込み量を削減するための改善点の1つです。ALTER
このテストハーネスを使用して試してみました。
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
ステートメントsys.dm_io_virtual_file_stats(DB_ID(N'248749'), DEFAULT)
を実行する前後にチェックALTER
しましたが、違いは次のとおりです。
デフォルト(オフライン) ALTER
- データファイルの書き込み/書き込まれたバイト数:34,809 / 2,193,801,216
- ログファイルの書き込み/書き込まれたバイト数:40,953 / 1,484,910,080
オンライン ALTER
- データファイルの書き込み/書き込まれたバイト数:36,874 / 1,693,745,152(22.8%の低下)
- ログファイルの書き込み/書き込まれたバイト数:24,680 / 866,166,272(41%の低下)
ご覧のとおり、データファイルの書き込みがわずかに減少し、ログファイルの書き込みが大幅に減少しました。