Neueste Kommentare
Hallo Herr Ricken, danke für diesen Artikel. Allerdings hilft er mir nicht weiter, wenn eine Datenbank wirklich verkleinert werden muss um freien Speicher zu bekommen. Ein Kunde hat eine 800 GB Datebank. Nach einer Datenbereinigung ist die DB eigentlich nur noch ca. 80 GB groß und wird durch den regelmäßigen Einsatz von Löschskripten auch nicht mehr größer als ca. 100 GB. Ohne Shrinken kommt man aber nicht mehr an den Speicherplatz heran. Was wäre denn Ihre Empfehlung für so einen Fall? Viele Grüße Markus Meyer
Klasse Uwe, ich freue mich schon auf weitere Artikel von Dir.
Hallo Torsten, ACK! - aber eine 600 GB-Datenbank für mehrere Stunden offline zu nehmen, ist ein NOGO :) Es gibt SLA, die pro Jahr maximal 6 Stunden definieren! Ein SHRINKDATABASE ist in solchen Systemen IMMER der falsche Ansatz. Aber leider so z. B. in einer Anwendung erlebt, bei der JEDEN Montag ein Incident geöffnet wurde, um die Datenbank (DATA und LOG) zu verkleinern! Das die Kosten für diese "Snnlosaktion" deutlich über den Kosten für zusätzlichen Storage liegen, war/ist dem Business bis heute nicht zu vermitteln!
p.s.: kleiner Nachtrag zur starken Fragmentierung von Dateien im NTFS-Volume http://support.microsoft.com/kb/967351
gerne :-) ... auch bei 24/7 muss es ein Maintenance Fenster geben.
Lieber Torsten, herzlichen Dank für den Link; das Tool kannte ich noch nicht. Da aber für eine Defragmentierung ein DB-File offline genommen werden muss, ist es nicht wirklich sinnvoll in einer 24 / 7 - Anwendung ;( Bezüglich der "Erfahrungen eines dba" solltest Du nicht zu optimistisch sein :) Gerade im Segment Betrieb / Operations weltweit agierender Konzerne sollte man die Messlatte nicht sehr hoch setzen. Ich habe schlechte Erfahrungen in diesem Bereich mit den Kollegen "jenseits des Pazifks" machen müssen. Sicherlich nicht repräsentativ aber immer wieder erstaunlich!
Hallo Uwe, ich dachte über diesen Punkt sind die meisten DBA's schon raus - naja. Kleine Anmerkung noch zur hohen Fragmentierung auf Dateisystemebene, hier hilft Contig von Mark Russinovich (http://technet.microsoft.com/en-us/sysinternals/bb897428). Mit contig -a DatenbankName.mdf kann man sich die physikalische Fragmentierung ansehen. Und nach einem ALTER DATABASE [DatenbankName] SET OFFLINE kann man mit contig DatenbankName.mdf die Datenbank auf Dateisystemebene defragmentieren.
Für dieses Problem habe ich nun bei Microsoft Connect einen Bugreport erstellt: https://connect.microsoft.com/SQLServer/feedback/details/794983/alter-database-properties-shrink-size-of-databases-in-gui
Leider habe ich einen wichtigen Hinweis im Artikel vergessen: Das obige Verfahren kann nicht angewendet werden, wenn der DEFAULT einer Relation nicht für alle Zeilen eindeutig ist! z. B. - newid() - newsequentialid() Sobald ein jeweils unterschiedlicher Wert für JEDE Zeile einer Relation generiert werden kann, kann kein DEFAULT Value für alle Zeilen gelten und die Werte müssen direkt eingetragen werden.
Meinen ganz herzlichen Glückwunsch. Deine Artikel und Vorträge sind immer gern gesehen.
Gratulation! Willkommen im Klub!
Chapeau! Ich wünsche Dir einen schönen Tag, Torsten

Hallo Christian, danke für's Lesen meines Artikels und das er Dir gefallen hat. Statistiken sind IMMER am Index gebunden (ich lasse hier jetzt mal die "AutoStatistics" a' la _WA_SYS_ komplett aussen vor!) Was mir bei partitionierten Tabellen jedoch aufgefallen ist: - die Statistiken werden bei einem REBUILD eines partitionierten Index nicht korrekt berechnet! - ein separater UPDATE STATISTICS berechnet dann die korrekten Werte Ich werde versuchen, nächste Woche noch mal einen Artikel über dieses Verhalten zu schreiben. Kann man aber sehr gut selbst ausprobieren: -- Erstellen der Partitionsfunktion CREATE PARTITION FUNCTION demo_col5 (date) AS RANGE LEFT FOR VALUES ('20130622', '20130623', '20130624', '20130625', '20130626', '20130627', '20130628', '20130629'); GO -- Erstellen des Partitionsschemas CREATE PARTITION SCHEME part_demo_col5 AS PARTITION demo_col5 ALL TO ([PRIMARY]); -- Partitionierung der Relation DROP INDEX ix_demo_col5 ON dbo.demo; GO CREATE INDEX ix_demo_col5 ON dbo.demo (col5) ON part_demo_col5 (col5); -- ein paar Daten ändern UPDATE dbo.demo SET col5 = getdate() WHERE Id <= 4; -- Wie sind die Statistiken? DBCC SHOW_STATISTICS ('dbo.demo', 'ix_demo_col5') WITH HISTOGRAM; -- nun werden die Statistiken neu erstellt UPDATE STATISTICS dbo.demo ix_demo_col5 WITH FULLSCAN; -- Und... -- Wie sind die Statistiken? DBCC SHOW_STATISTICS ('dbo.demo', 'ix_demo_col5') WITH HISTOGRAM; -- nun wird der Index neu erstellt! ALTER INDEX ix_demo_col5 ON dbo.demo REBUILD; -- Wie sehen die Statistiken aus? DBCC SHOW_STATISTICS ('dbo.demo', 'ix_demo_col5') WITH HISTOGRAM; Man kann sehr gut erkennen, dass beim UPDATE STATISTICS die korrekten Daten ausgegeben werden, bei einem REBUILD werden sie gesampled obwohl ich einen FULLSCAN eingegeben habe. Ich werde das mal näher untersuchen und mit einem Ergebnis hier bloggen... Bin jetzt selbst gespannt, woran das liegt :)

Hallo Uwe, danke für den excellenten Artikel. Bei uns in der Firma betreiben wir große Datenbanken (100GB +) mit Partitionen. Wir richten die meisten Indexe an den Partitionen aus, was den Vorteil hat das nur Indexe mit sich ändernden Daten einen Reorg bzw Rebuild unterlaufen müssen. Wie verhält es sich hier mit den Statistiken? Hängen diese direkte an dem partitionierten Index oder gehen diese über den kompletten Datenbestand. Gruß Christian
Genau. Beide Beiträge ergänzen sich hervorragend.
Hallo Frank, vielen Dank für die wichtigen Hinweise. Ich hoffe aber, dass durch den Artikel klar, ist, dass es sich um DDL-Operationen handelt und somit die Einschränkungen von Metadatenmanipulationen zu berücksichtigen sind. Sorry - ich wußte nicht, dass Du auch schon (wenn auch vor vielen Jahren) einen ähnlichen Artikel geschrieben hast. Ich habe nur etwas mehr "unter die Haube" geschaut :)

Unterschied zwischen DELETE und TRUNCATE
DELETE logged die Daten für jede einzelne Zeile, die von dem Statement betroffen sind und entfernt physikalisch den Record aus der Seite. Fährt man seine Datenbanken im "Full Recovery" Modus, kann die Aufzeichnung eines jeden ei...
Nice! Eine kleine Anmerkung habe ich dennoch. :-) Ist zwar nicht die Stossrichtung deines Beitrages, aber dennoch solltest du vielleicht erwähnen, dass es zwischen DELETE und TRUNCATE einige weitere gewichtige Unterschiede gibt. * TRUNCATE funktioniert nicht, wenn Foreign Keys im Spiel sind. Von daher wird man es bei den meisten Tabellen eines OLTP Systems kaum einsetzen können * TRUNCATE setzt einen evtl. vorhandenen IDENTITY Wert zurück. Das sollte zwar kein grosses Problem sein, aber man sollte sich dessen bewusst sein, bevor man ein TRUNCATE absetzt. * TRUNCATE ist immer alles in einer Tabelle. Es funktioniert aus eben diesen Gründen, die du sehr schön beschrieben hast, leider nicht, dass man ein TRUNCATE TABLE .... WHERE.... ausführen kann (....nachdem ich den 1.ten Kaffee ausgetrunken habe, ist mir dann auch aufgefallen, dass du das ja bereits erwähnst) ...der Einfachheithalber könnten wir auch einen Querverweis einbauen (Shameless plug....).
Klasse Überblick über die Verwaltungsdaten hinter den Daten!

Hallo Frank, ja - das war schon ein herbes Erlebnis. Ich bin sehr froh, dass es endlich vorbei ist. Christoph, vielen Dank für die Glückwünsche. Beim nächsten Treffen geht die erste Runde auf mich ;)
29.04.15 @ 10:58:54