Archiv nach Kategorien: Datenbank

Datenbank migrieren

Eine Datenbank von SQL Server 2000 auf SQL Server 20XX zu portieren stellt manchmal ein Problem dar.
Soll man das mit dem DTS Wizard für Daten Im-/Export machen?
Ich persönlich hänge die Datenbank auf dem alten Server ab und hänge sie in den neuen Server ein.
Meistens geht das ohne größere Probleme.

Zunächst muss sichergestellt sein, dass niemand mehr auf die Datenbank zugreift. Im Query Analyzer gibt man diese Befehle ein:

use master
sp_detach_db 'datenbank', 'true'
use master
sp_detach_db 'datenbank', 'true'

Die Datenbank ist damit abgehängt und ist auf dem alten Server nicht mehr verfügbar. Danach kann man die zugrundeliegenden Dateien (“.MDF” und “.LDF”, siehe Codezeile unten) aus dem Daten-Verzeichnis des alten Servers in das Daten-Verzeichnis des neuen Servers kopieren.

Der nächste Befehl (eingegeben im Query Analyzer der neuen Servers) hängt die Datenbankdateien auf dem neuen Server wieder ein:

sp_attach_db 'datenbank', 'C:\Programme\Microsoft SQL Server\MSSQL\Data\datenbank_Data.MDF', 'C:\Programme\Microsoft SQL Server\MSSQL\Data\datenbank_Log.LDF'
sp_attach_db 'datenbank', 'C:\Programme\Microsoft SQL Server\MSSQL\Data\datenbank_Data.MDF', 'C:\Programme\Microsoft SQL Server\MSSQL\Data\datenbank_Log.LDF'

Der Speicherort muss natürlich exakt angegeben werden. Nach ein paar Sekunden (oder Minuten, je nach Größe der Datenbank) steht die Datenbank auf dem neuen Server wieder zur Verfügung.

Beim Einhängen wird die Datenbank konvertiert. Meistens geht das gut. Manchmal auch nicht :) Dann muss man manuell nacharbeiten. Alles in allem ist dies die einfachste und schnellste Möglichkeit, eine Datenbank von SQL Server 2000 zu migrieren, die ich so kenne.

Doppelten Eintrag in Datenbank löschen

Natürlich lohnt es nicht, einen Blogeintrag über das Löschen von Datensätzen in einer Datenbank zu schreiben. Es sei denn, der Dorftrottel hat die Tabelle entworfen… Dann kann es nämlich durchaus vorkommen ist es meistens so, dass in der Tabelle kein Index und keine Art von Schlüssel vorkommt. Natürlich wird bei der Dateneingabe auch nie geprüft, ob ein entsprechender Eintrag vielleicht schon vorhanden ist. Es kommt dann wie es kommen muss: Irgendwann fallen doppelte (in allen Feldwerten gleichlautende) Datensätze an. Und dann ist es nicht mehr weit, bis jemand schreit, dass ein Datensatz oder n Einträge gelöscht werden müssen.

Wie löscht man nun gleiche Einträge, wenn sich die Datensätze nicht unterscheiden? Mit SQL geht’s nicht, da man keine Einschränkung zur Auswahl eines Datensatzes findet. Mit dem Management-Studio geht’s auch nicht, es meckert, dass eventuell alle Datensätze betroffen sind. Also einfach alle Datensätze wegpölen und neu eingeben?

Mit SQL geht’s aber doch, wenigstens seit SQL Server 2005. Dort kann man in der DELETE Anweisung (wie auch in der UPDATE Anweisung) ein TOP ROW angeben. Um den ersten eines doppelten Eintrags zu löschen, reicht es

DELETE TOP (1) FROM tabelle WHERE feld = xyz
DELETE TOP (1) FROM tabelle WHERE feld = xyz

zu schreiben. Es wird dann tatsächlich der erste (bzw. beliebige) Eintrag eines doppelten (drei-, vier-, n-fachen)  Eintrags gelöscht.

7 Tipps für Datenbanken

  1. Datenbanken sind nie das, was sie zu sein scheinen
  2. Ein Join geht erbärmlich oft in die Hose
  3. Use The Views!
  4. Lies verdammt noch mal die Dokumentation zum Server
  5. Du sollst nicht optimieren
  6. SELECT ALLES OHNE SINN UND VERSTAND
  7. Feed me, please!

1. Man kann es auch umformulieren: Datenbanken verhalten sich nie so, wie du es gerne hättest. Wenigstens dann nicht, wenn sie schon ein paar Jährchen auf dem Buckel haben und du nicht mit ihnen aufgewachsen bist. Datenbanken sind organische Wesen. Sie wurden einst von einem hochspezialisierten Datenbankkomponisten auf harmonische Weise entworfen und normalisiert. Die meisten von ihnen erleiden dennoch über kurz oder lang den Daten GAU. Eifrige Programmierer schrauben dann nach Gutdünken an Feldern und Funktionen herum, fügen hier noch ein varchar(max) hinzu, erweitern die Tabelle X um 20 Felder “einfach mal so für die Zukunft” oder killen einfach ein paar Indizes (oder noch besser: legen auf alle Felder einen Index, yeah!) Die Datenbank ist dann irgend etwas, wo Daten drin sind. Die Dokumentation von damals ist hoffnungslos falsch. Nichts verhält sich so, wie die Tabellen- oder Funktionsnamen suggerieren möchten. Und dann sitzt du davor und musst drumherum ein Programm basteln, was möglichst effizient die Daten präsentiert. Was tun? Siehe Punkt 3.

2. Joins sind oft benutzte Befehle bei Abfragen, so dass man öfters hört: “Am besten erst einmal alles zusammen joinen, damit man möglichst alle Daten beisammen hat. Wird schon irgendwie klappen.” Abgesehen von der totalen tollen Performance, die man dabei erwarten kann (…), kann das übermäßige joinen zu total tollen Fehlern führen. Das schlimme dabei: die Fehler merkt man oftmals nicht. Tabellen, die in einer Datenbank unter Punkt 1 liegen, haben natürlich auch redundante Daten in sich. Darauf einen Join ausführen, ist abentuerlich. Wenn dann noch Aggregatfunktionen ins Spiel kommen, fällt man unter Garantie auf die Nase. Bei doppelten (drei-, vier-, …-fachen) Schlüsseln ist dann vorbei mit lustig. Wenn man viel Glück hat, bemerkt man z. B. bei SUM exorbitant hohe Werte, die niemals stimmen können. Wie gesagt, wenn man Glück hat. Hat man Pech und das Aggregat ist z. B. AVG wird man niemals einen Fehler bemerken, bis der Controller vom Kunden kommt…

3. Wenn ich Datenbanken mit verkorksten Tabellen finde, mache ich folgendes: Ich versuche, so viel Informationen zu den Tabellen und deren Beziehungen zu bekommen. Diese Information bekommt man am ehesten aus vorhandenen Programmen und vorhandenen Programmierern ;) Danach bastle ich mir ein paar Views, die die Tabellen meiner Meinung nach am besten widerspiegeln. Meistens braucht man eh nicht alle Informationen, die in einer Tabelle stecken. Natürlich vermeide ich dabei Fehler wie varchar(max) und benutze stattdessen decimal(18,2) und konvertiere mir die Werte entsprechend. Mit diesen Views kann man dann schon eher programmieren, da man hoffentlich weiß, was man selbst dort gemacht hat. Views sind eine tolle Erfindung, auch wenn sie vielleicht ein wenig Performance klauen. Aber besser eine aufgeräumte View als eine verbügelte Originaltabelle.

4. Vor einigen Jahren habe ich mir mal die Dokumentation zum MS SQL Server 2005 durchgelesen. Ich gebe es zu: Ich habe dabei Dinge erfahren, die mich massiv staunen ließen. Ich habe manchmal das Gefühl, dass viele Programmierer ihr Wissen in Teilbereichen einfach auf einem bestimmten Stand lassen. Ihr Heim ist der Uralt Query Analyzer vom SQL Server 2000, ihr Kompatibilitätslevel ist 100 %. Aber nur zum SQL Server 2000. Moderne Datenbank Server leisten eine Menge mehr als nur ein paar Abfragen ausführen. Sie sind meistens genau so umfangreich wie eine Programmiersprache unter einer normalen IDE. Viele SQL Abfragen oder Workflows hat man vor 10 Jahren einmal gelernt und benutzt sie immer wieder. Es lohnt sich aber mal zu googlen, ob das vorliegende SQL Server System die gleichen Dinge nicht schon von Haus aus anbietet.

5. Und dann kommen noch die ganz taffen Hardcore Cracks, die eine SQL Abfrage extrem tunen und dem Abfrageoptimierer einige wertvolle Hints mit auf den Weg geben, weil sie es einfach viel besser wissen. Und jetzt mal unter uns: glaubt wirklich jemand daran, dass ein durchschnittlich begabter Programmierer dem SQL Server sagen kann, was er tun soll? Ob das die Entwickler des Servers (und demzufolge auch des Abfrageoptimierers) nicht am besten wissen? Bitte, lasst einfach den Optimierer optimieren. Vermutlich kann er es wesentlich besser als wir es jemals können werden. Und wenn eine Abfrage total lahmt, kann man sich dazu einmal den Ausführungsplan anzeigen lassen. Dabei kann man sich vom Abfrageoptimierer sogar noch ein paar Tipps geben lassen! Die Hinweise des Optimierers beschränken sich zwar lediglich auf fehlende Indizes, aber immerhin. Im Laufe der Jahre sind die SQL Server extrem leistungsfähig geworden. Alle Tuning-Tipps aus dem letzten Jahrhundert sind heute meistens obsolet. Ja, einige sind sogar kontraproduktiv und gehen nach hinten los. Es lohnt sich daher immer, sich hin und wieder den Ablaufplan einer Abfrage anzusehen und dabei einzelne Parameter zu verändern. Und dann probier doch mal deine Tuning-Tricks von anno 1999 aus. Staunen garantiert!

6. Man kann es niemals überstrapazieren: Vergiss “SELECT *”! Muss man das wirklich noch weiter ausführen? Es geht nicht wirklich um die Geschwindigkeit (Mitunter werden Abfragen mit Einzelfeldern genau so schnell ausgeführt wie  ein SELECT *, wenigstens auf lokalen Systemen). Und spätestens bei Aggregaten musst du eh wieder alle Felder einzeln aufführen, ätsch!

7. Alles, was der SQL Server machen kann, soll der SQL Server auch machen. Verlagere alles auf den Server, was irgendwie geht. Der Server braucht Beschäftigung, also mach ihm die Freude. Schöner Nebeneffekt: Migration und Portierung, ja selbst die Wartung wird einfacher. Du musst keinen Sourcecode in deinen Programmen ändern, du änderst einfach alles auf dem Server. Und dank SQL Standardisierung (hüstel) kannst du einfach von einem Datenbanksystem auf das andere wechseln. (Ok, ich geb’s zu: etwas Zeit musst du dafür schon mitbringen.)

VIEWS und die TOP 100

Oftmals erstellt man mal schnell eine View zum Testen und beschränkt die Ausgabe über eine TOP n Klausel, damit man nicht so lange warten muss. (Diese Klausel wird übrigens auch vom Abfrageoptimierer mit in die Auswahl des optimalen Ausführungsplan einbezogen.)

Das ist schön und gut, hat aber einen Haken: meistens vergisst man die TOP n Klausel wieder aus der View zu entfernen. Manchmal fällt einem das im Produktivbetrieb auf (z. B. weil man immer genau 100 Abfrageergebnisse bekommt). Hat man dagegen TOP 25 PERCENT verklausuliert, fällt das niemals mehr auf, außer natürlich dem Kunden, der dann bitterböse wird ;)

Ich versuche dann, mir eine Gedankenstütze zu bauen, indem ich im SELECT ein [Nimm die TOP n Klausel wieder heraus!] einpflanze. Sehr oft erinnere ich mich dann wieder an den Feldnamen, wenn die View produktiv gehen soll und ich vorher alles noch einmal durchchecke.