2009-02-26 10 views
2

Wir haben eine Legacy-Datenbank, die Strings als Primärschlüssel verwendet. Ich möchte Objekte auf dieser alten Datenbank implementieren, um eine Geschäftslogik besser zu implementieren und dem Benutzer mehr Funktionalität zu bieten.NHibernate und String Primärschlüssel

Ich habe in Orten gelesen, dass die Verwendung von Zeichenfolgen für Primärschlüssel auf Tabellen ist schlecht. Ich frage mich, warum das so ist? Liegt es an den Problemen der Groß-/Kleinschreibung? Zeichensätze?

... Warum ist das besonders schlecht für NHibernate?

... und weiter nach ... wenn Strings schlechte Primärschlüssel erzeugen, lohnt es sich, die Primärschlüssel in der Datenbank durch Ints oder GUIDs oder ähnliches zu ersetzen? (Wir haben nur etwa 25-30 Tabellen beteiligt)

Antwort

5

Okay, ich werde einen Stich haben. Ich werde ein paar schnelle Vorbehalte geben - ich bin kein Experte für Datenbanken und meine Erfahrung ist mit Hibernate (Java) anstatt NHibernate, aber hier geht es.

Ich denke, das Problem der Primärschlüssel als Zeichenfolgen ist mit dem SQL-Datentyp zu tun, der verwendet wird, um sie in der Datenbank zu repräsentieren. Da der Primärschlüssel immer beim Einfügen, Abfragen usw. verwendet wird, muss die Datenbank-Engine viel Zeit mit dem Vergleich von Primärschlüsseln verbringen. Wenn Sie Zahlen verwenden, werden diese einfach als Bytes gespeichert, mit denen Computer wirklich schnell fertig werden. Sobald Sie beginnen, Strings zu verwenden, steigen die Kosten dieser Operationen (hauptsächlich Vergleiche) signifikant. Selbst wenn die Datenbank-Engine wirklich saubere Strategien zum Vergleichen von Schlüsseln verwendet, ist es immer noch schneller, Bytes als Bytes und nicht als Zeichenfolgen zu vergleichen.

Auf moderner Hardware wird dies jedoch viel weniger ein Problem als früher, und mit den Indizes fast das Problem verschwindet.

Ich weiß nicht genau, warum dies wirklich in Hibernate (und NHibernate) ist aber meiner Erfahrung nach, weil meine Anwendung ein komplexes Diagramm von Objekten hat, die häufig Referenzen auf andere persistente Objekte haben, oft als Listen oder Die Referenzen werden alle unter Verwendung der ID des anderen Objekts gespeichert, und aufgrund der Regeln, die ich für kaskadierende Speichervorgänge, Abrufen usw. eingerichtet habe, bedeutet dies, dass die Primärschlüssel ständig verwendet werden. Hibernate - was ich ziemlich mag - tendiert dazu, genau das zu tun, was er gesagt hat, und manchmal sagen Leute (besonders ich!), Dass sie wirklich dumme Sachen machen sollen. Daher führen selbst scheinbar einfache Aktualisierungen oder Abfragen dazu, dass recht komplexes SQL generiert wird.

Also - zusammenfassend - Strings als Primärschlüssel sind schlecht wegen der Kosten von einfachen Operationen auf ihnen und die Verwendung von Hibernate kann dies vergrößern. In der Praxis haben moderne Datenbank-Engines jedoch viele saubere Strategien, um sicherzustellen, dass der Performance-Hit nicht so schlecht ist. (Postgres - und vermutlich auch andere - erstellen standardmäßig Indizes für Primärschlüssel)

Für Ihr Follow-up - sollten Sie Ihre Schlüssel ersetzen? Nun, das hängt von der Leistung Ihrer Anwendung ab. Wenn die Leistung entscheidend ist, dann kann es für eine Anwendung mit hohem Volumen und sehr intensiver Anwendung eine gute Idee sein, sonst wird es wahrscheinlich nur minimalen Nutzen geben, mit dem Nachteil, dass Sie Zeit damit verbringen müssen, all Ihre Tabellen zu ändern. Sie können erwarten, dass Sie viel bessere Ergebnisse erzielen, indem Sie die Strategien verfeinern, die Sie mit NHibernate verwenden (dh Strategien abrufen und Kaskadierungen usw.).

1

Andy K scheint zu implizieren, dass Strings nicht als Bytes gespeichert werden. Das wäre lustig! In der Tat hängt alles davon ab, wie lange die Zeichenfolge PK ist und welche Sortierung Sie verwenden. Es könnte sogar schneller sein als bigint oder int identity und wird fast definitiv schneller sein als Guids. Wenn diese Strings etwas sind, nach dem Sie sowieso suchen müssen, dann würden Sie auf jeden Fall einen Index (vielleicht sogar einen Clustered-Index) brauchen, also warum nicht PKs machen!

0

Die Verwendung von Strings oder Zeichen fügt Ihrem System eine große Menge von accidental complexity hinzu. Stellen Sie sich diese Fragen:

  • wie die Groß-/Kleinschreibung zu behandeln;
  • wie Padding zu behandeln. In NHibernate können Sie eine kürzere Zeichenfolge einfügen, und die Datenbank fügt ihr im Hintergrund zwar einen Füllbereich hinzu, der sich jedoch nicht in Ihrer persistenten Entität widerspiegelt. Der Versuch, die Entität erneut mit der speicherinternen ID abzurufen, gibt null zurück;
  • wie Sie mit Codierungsproblemen umgehen. C# verwendet Unicode-Zeichenfolgen, Ihre Datenbank migriert nicht. Können Sie sagen, wie die Konvertierung gehandhabt wird? Ich denke nicht.
  • synthetische Ganzzahlschlüssel können von den meisten Datenbanken ohne zusätzlichen Aufwand automatisch generiert werden. Mit Strings erstellen Sie diese höchstwahrscheinlich "von Hand". Sofern Sie sie nicht hinter einer Factory verbergen (im DDD-Sinne), wird der Code durch das resultierende Domänenmodell unübersichtlich.

Obwohl die Performance-Overhead von andy K erwähnt wegen Indizierung verringern kann, noch viele Male tun Sie ID comparisions in-Speicher (Hash-Karten?) Und die DB Optimierungen gelten nicht da.

Ich habe an einem Projekt mit einer Legacy-Datenbank gearbeitet, die Primärschlüssel und keine Fremdschlüssel enthält. Wir dürfen das alte Schema nicht übernehmen, da eine Legacy-App von allen kleineren Aspekten abhängt. Ich habe das Gefühl, dass die Primärschlüssel der Zeichenfolge die Konsistenz mehr verletzen als die fehlenden Fremdschlüssel, da NHibernate die letzteren recht gut handhabt.

Verwandte Themen