Durch Erhöhen der Dezimalgenauigkeit wurde die Größe der Tabelle abrupt erhöht

7

Ich habe einen Tisch wie:

CREATE TABLE grid_rows(
    [grid_row_id] [int] NOT NULL,
    [grid_column_id] [smallint] NOT NULL,
    [decimal_val] [decimal](18, 6) NULL,
    [datetime_val] [datetime] NULL,
    [integer_val] [int] NULL,
    [string_val] [varchar](1024) NULL
)

Diese Tabelle hat einige 1,037,560 rows

exec sp_spaceused "grid_rows" gives:
rows         reserved    data
1,037,560    461,768KB  302,648KB`

Nach dem Ändern der Genauigkeit von (18, 6) auf (24,6) dh ALTER TABLE grid_rows ALTER COLUMN decimal_val decimal(24, 6)

exec sp_spaceused "grid_rows" gives:
rows         reserved     data
1,037,560    641,352KB  560,832KB

Der von decimal(18,6)is 9 bytesund dem von (24, 6)is zugewiesene Speicherplatz 13 bytes. MSDN-Referenz

The reserved space has increased by around 179,584 KB and data space by 260,000KB. Shouldn't it be increased by 1,037,560 * 4/1024 = 4052 KB

Dumper
quelle
Können Sie klarstellen, was genau Ihre Frage ist?
Ich bin in der Lage , das Problem zu reproduzieren, und interessanterweise der Raum genutzt wird auch anders sein , wenn Sie die Tabelle mit erstellen decimal(24, 6)gerade von Anfang an : für eine Tabelle mit 1024 Zeilen, ich bin immer 48KB mit decimal(18, 6), 56KB mit decimal(24, 6)und 72KB mit decimal(18, 6) then alter to decimal(24, 6). Ich habe jedoch keine Erklärung dafür.
Lâm Tran Duy
Wenn ich raten müsste, würde ich sagen, dass die Datenseiten jetzt 2 Kopien des fraglichen Feldes enthalten. Die alte Kopie, die nicht mehr verwendet wird, und die neue, größere Kopie, die verwendet wird.
Max Vernon
@MaxVernon - aber sollte es dann nicht nur die Größe des reservierten Speicherplatzes beeinflussen, sondern die tatsächliche Datengröße?
Lâm Tran Duy
4
Eine andere Sache, die die Tabellengröße erhöhen kann, sind Seitenteile. Wenn Ihre Seiten ziemlich voll sind, kann das Erhöhen der Größe einer Spalte dazu führen, dass einige Daten auf eine neue Seite verschoben werden.
Aaron Bertrand

Antworten:

4

Beachten Sie, dass die abgelegte Spalte physisch noch in der Zeile vorhanden ist .

Aber der wahre Killer ist wahrscheinlich, dass, wenn dies ein Heap ist (Tabelle ohne Clustered-Index), Zeilenaktualisierungen, die die Zeilengröße erhöhen, eine Lawine der Weiterleitung verursachen können. Wenn Sie mit Seiten beginnen, die fast zu 100% voll sind, passt jede Zeilenerhöhung dazu, dass die Zeile nicht mehr in die Seite passt. Daher muss ein Vorwärtsdatensatz an Ort und Stelle belassen und die Zeile an einer anderen Stelle platziert werden. Wiederholen Sie dies für jede Zeile (Extremfall) und Sie haben ein ziemlich böses Szenario.

Wenn es sich um einen B-Baum handelt, führt dasselbe Szenario zu besseren Seitenaufteilungen, da die kopierten Zeilen während der Aufteilung den Platz zwischen den Zeilen auf der Seite zurückfordern , was im Fall der Heap-Weiterleitung nicht der Fall ist.

Remus Rusanu
quelle
3

Ich habe gerade die physischen Daten von Seiten verwendet DBCC INDund DBCC PAGEgelesen, auf denen DECIMAL(4,2)Daten gespeichert waren , die anschließend in DECIMAL(8,4)Daten geändert wurden . Das alte Feld wird jetzt als aufgeführt DROPPED, wobei ein anderes Feld die neuen Daten enthält.

        CREATE TABLE TestDec
        (
            DecimalValue DECIMAL(4,2)
        );

        INSERT INTO TestDec VALUES (16.25);
        SELECT * FROM TestDec;

        EXEC sp_spaceused 'TestDec';

        DBCC IND('Test', 'TestDec', -1)

                    /* 20267501 happens to be the page in my database, yours WILL 
                       be different */
        DBCC TRACEON(3604) /* display output from DBCC PAGE */
        DBCC PAGE('Test',1,20267501,3) WITH TABLERESULTS

        ALTER TABLE TestDec ALTER COLUMN DecimalValue DECIMAL(8,4)
        DBCC PAGE('Test',1,20267501,3) WITH TABLERESULTS

Geben Sie hier die Bildbeschreibung ein

Die Zeilen 46 und 47 zeigen die relevanten Elemente.

Dies zeigt an, dass die vorhandenen Daten an einen neuen physischen Speicherort kopiert werden, wenn die Dezimalfeldgröße geändert wird.

Max Vernon
quelle
4
Ja, und dies könnte definitiv zu Seitenteilen usw. führen. Ich glaube, Sie müssen eine Neuerstellung durchführen, um den von den abgelegten Spalten belegten Speicherplatz wiederherzustellen.
Aaron Bertrand