2011-01-17 4 views
2

Ich brauche etwas Input, wie man eine Datenbankschicht entwirft.Datenbank, Anforderungen, Leistung, Cache

In meiner Anwendung habe ich eine Liste von T. Die Informationen in T haben Informationen aus mehreren Datenbanktabellen.

Es gibt natürlich mehrere Möglichkeiten, dies zu tun. Zwei Möglichkeiten, die ich mir vorstellen ist:

gesprächig Datenbankschicht und zwischenspeicherbar:

List<SomeX> list = new List<SomeX>(); 
foreach(...) { 
    list.Add(new SomeX() { 
     prop1 = dataRow["someId1"], 
     prop2 = GetSomeValueFromCacheOrDb(dataRow["someId2"]) 
    }); 
} 

Das Problem, das ich mit dem oben sehen, ist, dass, wenn wir eine Liste von 500 Titel wollen, könnte es potenziell 500 Datenbankanfragen stellen Mit der ganzen Netzwerklatenz und dem. Ein weiteres Problem ist, dass die Benutzer gelöscht werden konnten, nachdem wir die Liste aus der Datenbank bekommen haben, aber bevor wir versuchen, sie aus cache/db zu bekommen, was bedeutet, dass wir Null-Probleme haben werden. Was wir manuell handhaben müssen. Die gute Sache ist, dass es gut cachefähig ist.

nicht gesprächig, aber nicht zwischenspeicherbar:

List<SomeX> list = new List<SomeX>(); 
foreach(...) { 
    list.Add(new SomeX() { 
     prop1 = dataRow["someId1"], 
     prop2 = dataRow["someValue"] 
    }); 
} 

Das Problem, das ich mit dem oben sehen, ist, dass seine schwer zu Cache, da möglicherweise alle Benutzer einzigartige Listen haben. Das andere Problem ist, dass es viele Joins geben wird, die zu einer Menge von Lesevorgängen gegen die Datenbank führen können. Die gute Sache ist, dass wir sicher wissen, dass alle Informationen existieren, nachdem die Abfrage ausgeführt wird (innere Verknüpfung usw.)

nicht so gesprächig, aber immer noch zwischenspeicherbar

Eine dritte Möglichkeit zur ersten Schleife könnte durch die Datenzeilen und sammeln alle notwendigen someId2 und machen dann eine weitere Datenbankanforderung, um alle SomeId2-Werte zu erhalten.

+1

Gibt es einen guten Grund, das O/RM-Rad neu zu erfinden? Das Problem wurde von Entity Framework, NHibernate und einer Reihe anderer Projekte gelöst. – Bergius

+1

Es gibt Vor- und Nachteile eines O/R-Mappers. Und das Problem/die Frage existiert immer noch, wenn wir die Site nur mit gespeicherten Prozeduren ausführen möchten. – Patrik

+0

Können Sie Einzelheiten dazu angeben, wie die Daten in Ihren Tabellen strukturiert sind? Ich nehme an, dass someId1 eine Benutzer-ID darstellt und someValue Eigenschaften dieses Benutzers (?) Darstellt und dass diese Eigenschaften in verschiedenen Tabellen gespeichert sind. Abhängig von Ihrer Antwort könnte es besser sein, ein paar Tabellen neu zu gestalten. – NotMe

Antwort

1

"Das Problem, das ich mit dem oben genannten sehe, ist, dass, wenn wir eine Liste von 500 Elementen wollen, könnte es möglicherweise 500 Datenbankanfragen. Mit allen Netzwerk-Latenz und das."

Wahr. Sie können auch unnötige Konflikte verursachen und Serverressourcen verbrauchen, während Sie bei einer Abfrage die Sperren beibehalten.

"Ein weiteres Problem ist, dass die Benutzer gelöscht werden konnten, nachdem wir die Liste von der Datenbank erhalten haben, aber bevor wir versuchen, sie aus dem Cache/db zu bekommen, was bedeutet, dass wir Null-Probleme haben."

Wenn ich dieses Zitat nehmen, dann dieses Zitat:

„Die gute Sache ist, dass es sehr zwischenspeicherbar ist.“

Ist nicht wahr, weil Sie veraltete Daten zwischengespeichert haben. Also streiche den bisher einzigen Vorteil ab.

Aber um Ihre Frage direkt zu beantworten, ist das effizienteste Design, das zu sein scheint, die Datenbank für das zu verwenden, wofür es gut ist, ACID-Konformität und verschiedene Einschränkungen, vor allem pk und fk, Aber auch, um aggregierte Antworten zurückzugeben, um Rundreisen und verschwendete Zyklen auf der App-Seite zu reduzieren.

Das bedeutet, dass Sie entweder SQL in Ihren App-Code eingeben, der von der Code Thought Police als Unendlich Schlechtes Geschmacksempfinden eingestuft wurde, oder zu sprocs gehen. Entweder funktioniert es.Wenn du den Code in die App einfügst, wird er wartbarer, aber du wirst niemals zu eleganteren OOP-Partys eingeladen.

+0

"Indem Sie den Code in die App einfügen, wird er wartbarer" .. was? – NotMe

+0

"Ist nicht wahr, weil Sie veraltete Daten zwischengespeichert haben. Also schlagen Sie den einzigen Vorteil, den Sie bisher gemacht haben." Wenn wir die Löschungen/Aktualisierungen sowohl in der Datenbank als auch im Cache behandeln, sind die Daten vermutlich nicht veraltet. Also argumentiere ich immer noch, dass es cachefähig ist. – Patrik

0

Einige Vorschläge:

SQL ist eine Reihe basierte Sprache, entwirft so die Dinge nicht über Schleifen laufen. Auch bei gespeicherten Prozeduren werden ab und zu Cursor angezeigt, wenn eine mengenbasierte Abfrage das Problem löst. Versuchen Sie also immer, die Informationen mit 1 Abfrage abzurufen. Jetzt ist das manchmal nicht möglich, aber in der Mehrheit wird dies sein. Sie können Views auch so gestalten, dass die Abfrage einfacher wird, wenn Sie ein Schema mit vielen Tabellen haben, um die Informationen abzurufen, die für eine Anweisung benötigt werden.

Verwenden Sie Proxys. Nehmen wir an, ich habe ein Objekt mit 50 Eigenschaften. Zunächst zeigen Sie dem Benutzer eine Liste von Objekten an. In diesem Fall würde ich einen Proxy der wichtigsten Eigenschaften erstellen und dem Benutzer anzeigen, vielleicht zwei oder drei wichtige, wie Name, ID usw. Dies verringert die Menge der ursprünglich gesendeten Informationen. Wenn der Benutzer das Objekt tatsächlich bearbeiten oder ändern möchte, führen Sie eine zweite Abfrage durch, um das "vollständige" Objekt zu erhalten. Bekomme nur, was du brauchst. Dies ist besonders bei der Serialisierung von XML zwischen den Layern wichtig.

Kommen Sie mit einer Paging-Strategie. Die meisten Systeme funktionieren gut, bis sie eine Menge Daten erhalten, und dann wird die Abfrage angehalten, da sie 1000 Datensätze/Datensätze wiederherstellt. Seite früh und oft. Wenn Sie eine Webanwendung ausführen, ist wahrscheinlich das direkte Paging direkt in der Datenbank die leistungsstärkste Methode, da nur die ausgelagerten Daten zwischen den Layern gesendet werden.

Datencaching hängt von den Daten ab. Für hochflüchtige Daten (die sich ständig ändern) lohnt sich das Caching nicht. Bei halbflüchtigen oder nicht flüchtigen Daten kann sich Caching lohnen, aber Sie müssen den Cache entweder direkt oder indirekt verwalten, wenn Sie ein eingebautes Framework verwenden.

Ein guter Ort, um einen Cache zu verwenden, ist, dass Sie eine Postleitzahl haben. Certianisch, diese ändern sich nicht so oft und Sie können diese zur Leistungssteigerung zwischenspeichern, wenn Sie eine Postleitzahl in Ihrer Anwendung haben. Dies ist nur ein Beispiel, aber das Zwischenspeichern von IMO hängt vom Datentyp ab.

+0

"Ein guter Ort, um einen Cache zu verwenden, ist, dass Sie eine Postleitzahl haben." Nehmen wir an, dass someId2 aus meinem Beispiel zipCodeId ist, aber der zipCode in einer anderen Tabelle ist. Wenn ich mich anmelde, wird es mich jedes Mal kosten, wenn ich diese Frage mache, aber wenn ich alle Postleitzahlen zwischenspeichere und nur die ID abrufe, wird es ohne den Beitritt schneller. – Patrik