Gibt es eine Möglichkeit, den Spaltendatentyp als reine Metadatenoperation zu ändern?
Ich glaube nicht, so funktioniert das Produkt jetzt. Es gibt einige wirklich gute Umgehungsmöglichkeiten für diese in Joes Antwort vorgeschlagene Einschränkung .
... führt dazu, dass SQL Server die gesamte Tabelle neu schreibt (und 2x Tabellengröße im Protokollbereich verwendet)
Ich werde auf die beiden Teile dieser Aussage getrennt antworten.
Umschreiben der Tabelle
Wie ich bereits erwähnt habe, gibt es keinen Weg, dies zu vermeiden. Das scheint die Realität zu sein, auch wenn es aus unserer Sicht als Kunden keinen Sinn ergibt.
Ein Blick DBCC PAGE
vor und nach dem Ändern der Spalte von 4000 auf 260 zeigt, dass alle Daten auf der Datenseite dupliziert wurden (meine Testtabelle hatte 'A'
260-mal in der Reihe):
Zu diesem Zeitpunkt befinden sich zwei Kopien der exakt gleichen Daten auf der Seite. Die "alte" Spalte wird im Wesentlichen gelöscht (die ID wird von "id = 2" in "id = 67108865" geändert), und die "neue" Version der Spalte wird aktualisiert, um auf den neuen Versatz der Daten auf der Seite zu verweisen:
Verwenden von 2x Tabellengröße im Protokollbereich
Durch WITH (ONLINE = ON)
das Hinzufügen am Ende der ALTER
Anweisung wird die Protokollierungsaktivität um etwa die Hälfte reduziert. Dies ist also eine Verbesserung, die Sie vornehmen können, um die Anzahl der Schreibvorgänge auf die Festplatte bzw. den erforderlichen Speicherplatz zu verringern.
Ich habe dieses Testgeschirr benutzt, um es auszuprobieren:
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
Ich habe sys.dm_io_virtual_file_stats(DB_ID(N'248749'), DEFAULT)
vor und nach dem Ausführen der ALTER
Anweisung überprüft , und hier sind die Unterschiede:
Standard (Offline) ALTER
- Datendateischreibvorgänge / geschriebene Bytes: 34.809 / 2.193.801.216
- Schreibvorgänge / geschriebene Bytes in der Protokolldatei: 40.953 / 1.484.910.080
Online ALTER
- Schreibvorgänge in Datendateien / geschriebene Bytes: 36.874 / 1.693.745.152 (22,8% Rückgang)
- Schreibvorgänge in Protokolldateien / geschriebene Bytes: 24.680 / 866.166.272 (41% Rückgang)
Wie Sie sehen, sind die Schreibvorgänge in der Datendatei geringfügig und in der Protokolldatei erheblich zurückgegangen.