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.
update table set new_col = old_col where new_col <> old_col;
vor dem Ablegen zu machenold_col
.where new_col <> old_col
, können Sie einen Auslöser hinzufügen, der diese Änderungen im Laufe des Prozesses überträgt und am Ende des Prozesses entfernt, um den vollständigen Scan zu vermeiden, der ohne andere Filterklauseln ausgeführt wird. Immer noch ein potenzieller Leistungstreffer, aber viele kleine Beträge über die Dauer des Prozesses statt eines großen Treffers am Ende, wahrscheinlich (abhängig vom Aktualisierungsmuster Ihrer App für die Tabelle), was insgesamt weitaus weniger ergibt als dieser große Treffer .Nun gibt es eine Alternative je nach verfügbarem Speicherplatz in Ihrer Datenbank.
Erstellen Sie eine genaue Kopie Ihrer Tabelle (z. B.
new_table
), mit Ausnahme der Spalte, in der Sie vonNVARCHAR(4000)
bis kürzenNVARCHAR(260)
:In einem Wartungsfenster kopieren Sie die Daten von der "defekten" Tabelle (
table
) in die "feste" Tabelle (new_table
) mit einem einfachen BefehlINSERT ... INTO ... SELECT ....
:Benenne die "kaputte" Tabelle um
table
in etwas anderes:Benennen Sie die "feste" Tabelle um
new_table
intable
:Wenn alles in Ordnung ist, löschen Sie die "defekte" umbenannte Tabelle:
Es geht los.
Beantwortung Ihrer Fragen
Nein, derzeit nicht möglich
Nein.
( Siehe meine Lösung und andere. )
quelle