Ich habe viele große Tabellen (ungefähr 10 Millionen breite Zeilen), die regelmäßig in SQL Server 2016 geladen werden müssen, um schreibgeschützte Berichte zu erstellen. Ich möchte, dass diese Tabellen auf der Festplatte so klein wie möglich sind, und dies ist wichtiger als Leistungsverbesserungen beim Laden oder Abfragen.
Folgendes habe ich für die Tabellen getan, für die keine weitere Indizierung erforderlich ist:
- Erstellen Sie die Tabelle mit
DATA_COMPRESSION=PAGE
. - Verwenden Sie bcp, um die Daten aus einer Flatfile in die neue Tabelle einzufügen.
Die Spaltentypen in den Tabellen sind varchar (nie mehr als 512, nicht max), float, tinyint oder date (nicht datetime). Alle Spalten werden als nullwertfähig erstellt und es werden keine Primär- oder Fremdschlüssel definiert. Sie spielen für die Abfrage keine Rolle und die Tabellen werden niemals direkt aktualisiert. Standardkollatierung für alles ist SQL_Latin1_General_CP1_CI_AS
.
Wenn ich dies tue, kann ich auf sys.allocation_units
dieser Seite sehen, dass die Datenkomprimierung auf den Heap angewendet wurde, und ich kann sehen, sys.partitions
dass der Füllfaktor korrekt 0 (100%) ist. Da die Tabellen viel kleiner sind als unkomprimierte Tabellen, dachte ich, dass die Komprimierung durchgeführt wurde.
Wenn ich dann jedoch mit derselben Option neu erstelle DATA_COMPRESSION=PAGE
, wird die angeblich bereits komprimierte Tabelle um etwa 30% kleiner! Es sieht so aus, als würde es von ungefähr 17 Zeilen pro Datenseite auf 25 Zeilen pro Seite gehen. (Nur einmal. Ein erneuter Wiederaufbau macht ihn danach nicht kleiner als beim ersten Wiederaufbau.)
Die Fragen
Meine Fragen sind also: (a) Was ist hier los? und (b) gibt es eine Möglichkeit, diese extra kleine komprimierte Größe direkt beim Laden der Tabelle zu erhalten, ohne sie nach dem Laden der Daten neu erstellen zu müssen?