Praktische Methode zum Speichern einer „angemessen großen“ Datenmenge, die sich kaum jemals ändert?

13

Denken Sie an vorberechnete Nachschlagetabellen oder ähnliches. Ab wann ist es sinnvoller, eine Datenbank zu verwenden, anstatt Werte in meiner Anwendung fest zu codieren? Die Werte werden sich nicht ändern, und sie sind gut von den Wartungsentwicklern getrennt. 100 Werte, 1k, 10k, 100k? Ich möchte ungefähr 40k Werte speichern. Im Moment ist es eine maschinengenerierte switchAussage (über die VS2010 unglücklich ist).

bearbeiten:

Wenn jemand neugierig ist, habe ich Folgendes versucht: Meine Daten waren in zwei Float-Arrays mit 100.000 Elementen speicherbar, also habe ich das getan. Es dauerte ungefähr 20 Sekunden, um die Daten zu generieren, also habe ich das einmal gemacht und sie mit einem BinaryFormatter zu einer eingebetteten Ressource serialisiert. Das Entpacken der Daten dauert beim Start der Anwendung ungefähr 5 Millisekunden und übertrifft die von mir ersetzte Datenbankimplementierung (diese hartcodierten Werte wurden zuvor dort gespeichert) um fast das 45.000-fache.

Bryan Boettcher
quelle

Antworten:

5

Mein Vorschlag ist, die Daten entweder in einer Datei oder in einer Datenbanktabelle zu speichern. Wenn Geschwindigkeit kein Problem ist, fragen Sie die Datei oder Datenbank (Datenbank ist besser) zur Laufzeit ab. Wenn der Speicher kein Problem darstellt, Sie jedoch eine gewisse Geschwindigkeit wünschen, laden Sie die Daten in den Speicher, wenn das Programm gestartet wird. In C # könnten Sie eine Hash-Tabelle verwenden und anordnen, auflisten oder (beste Option) und eine Methode haben, um die zur Laufzeit benötigten Daten zurückzugeben (dh getDataValue (string keyToValue)).

Ich würde empfehlen, dass Sie die switch-Anweisung nicht verwenden, da sie sehr schwierig zu warten ist und einen großen exe-Footprint zur Folge hätte.

Hash-Tabelle zB http://support.microsoft.com/kb/309357

Adam f
quelle
Dies ist letztendlich das, was ich getan habe: Überprüfen Sie meinen aktualisierten Beitrag.
Bryan Boettcher
1
+1 für den Datenbankvorschlag. Datenbanken sind darauf ausgelegt, große Datenmengen zu speichern, und ermöglichen es Ihnen, diese sehr schnell abzurufen.
NoChance
Lesen Sie unter stackoverflow.com/questions/301371/… nach, warum es besser ist, ein Wörterbuch anstelle einer Hash-Tabelle zu verwenden. YMMV
Chris McKee
6

Persönlich bin ich in der Lage, eine beliebige Menge von Daten, die in der Anwendung fest codiert sind, zu speichern, bis keine Notwendigkeit mehr besteht, sie für eine bestimmte Bereitstellung oder einen bestimmten Hotfix zu optimieren.

Das Speichern und Zugreifen auf Daten mithilfe der C # -Schalteranweisung ist jedoch eine ziemlich schlechte Praxis, da das Datenspeicher- und Datenzugriffsmodell eng miteinander verknüpft ist und nur eine Methodenzugriffsmethode (nach Switch-Parametern) impliziert.

Ich würde es vorziehen, Daten in einer Hashtabelle oder einem Wörterbuch zu speichern und separate Klassen zum Abrufen der Daten und zum einmaligen Auffüllen von Suchwörterbüchern bereitzustellen.

Kürzlich fand ich es ziemlich praktisch, kleine DSLs zum Spezifizieren von Geschäftsregeln zu implementieren ( flüssige Schnittstelle für SiteMap oder Frage- Check-Methode "calc" für Steuerrechner zur Definition von Regeln) und dann ein separates Objekt zum Abfragen dieser Regeln bereitzustellen. Diese Technik würde sich gut für Switch-Szenarien eignen.

Einer der Vorteile einer solchen Zerlegung besteht darin, dass Sie eine Reihe von Ansichten für Ihre Daten implementieren können, ohne das XXXk-Linien-Blob zu berühren, das diese Daten definiert.

Valera Kolupaev
quelle
Ich habe die Antwort mit einigen Beispielen erweitert.
Valera Kolupaev
2

Eine 40k-Line-Switch-Anweisung ist etwas fragwürdig. Ich gehe davon aus, dass Sie noch Abfragen durchführen müssen, oder? Haben Sie versucht, die Daten zu kapseln? Verwenden Sie dann LINQ, um Abfragevorgänge für die Auflistung auszuführen und die Leistung zu testen. Holen Sie sich konkrete Zeiten, indem Sie Komponententests mit einem Timer wie StopWatch durchführen . Dann, wenn Sie denken, dass es einfach funktionieren könnte. Prüfen Sie, ob die Leistung für die Benutzer akzeptabel ist.

P. Brian Mackey
quelle
2

Ich hatte zweimal eine solche Anforderung. Die Anwendungen wurden eigenständig entwickelt, ohne dass ein Datenbank-Setup / -Zugriff erforderlich ist. In beiden Fällen habe ich XML-Dateien zum Speichern der Daten verwendet. In der ersten Version des 2.0 Frameworks habe ich die alten XML-Parsing-Aufrufe zum Nachschlagen von Daten verwendet. Bei der neueren Version des 3.5 Frameworks habe ich LINQ to XML verwendet, um das zu finden, was ich brauchte. In beiden Fällen wurde der Zugriff auf die Daten in Klassen eingekapselt.

jfrankcarr
quelle
1

Der Schlüssel dabei ist, sicherzustellen, dass Ihre öffentliche Schnittstelle Ihre Implementierung kapselt - aber das ist nicht Ihre Frage, und es gibt keinen Grund zu der Annahme, dass Sie dies nicht getan haben. Darüber hinaus ist es nur eine Frage von Leistung gegen Trauer (und Leistungsunterschiede sind es möglicherweise nicht wert, beachtet zu werden). Als praktische Lösung für die VS 2010-Ausgabe können Sie die case-Anweisung immer in eine Hierarchie von case-Anweisungen aufteilen. Die oberste Ebene kann eine von 10 anderen Methoden aufrufen, von denen jede beispielsweise eine case-Anweisung mit 4000 Fällen enthält. Sie könnten jede der 10 in eine eigene Datei schreiben, wenn Sie müssten. Ein bisschen hässlich, aber Sie generieren trotzdem Code.

Was die Nummer angeht, auf eine DB umzuschalten - es ist immer dann ein Problem, wenn keine DB verwendet wird.

bA
quelle
Ich schätze den Gedanken, dass meine Benutzeroberfläche die Implementierung kapselt: mit Sicherheit. Die Funktionalität wird durch eine GetValuesForInput-type-Methode verfügbar gemacht, und meine massive Aussage ist in der Implementierung verborgen.
Bryan Boettcher
1

Sie könnten so etwas wie SQL Compact verwenden. Legen Sie die Daten in eine Tabelle und belassen Sie die DB-Datei im Projekt. Tabellen sind für diese Datenmenge besser geeignet als eine switch-Anweisung.

Morgan Herlocker
quelle
1

Ich denke, das Schlüsselwort hier ist "kaum"

Wenn sich die Daten nie ändern - z. B. vorberechnete mathematische Werte, Farbkonstanten usw. -, behalten Sie sie im Code, solange die Größe für Sie überschaubar ist. Beachten Sie jedoch, dass bei Problemen mit der Leistung die case / switch-Anweisungen im Vergleich zu anderen Optionen sehr langsam sind.

Wenn sich die Daten kaum ändern - zum Beispiel Telefonvorwahlen, Landesgrenzen und dergleichen -, würde ich wahrscheinlich versuchen, die Daten auf irgendeine Weise extern zu halten. Besonders wenn es anfing, mehr als ein paar Dutzend Werte zu werden.

GroßmeisterB
quelle
1
Es kommt darauf an, wie gut der Compiler ist. Eine case-Anweisung in Delphi kann äußerst effizient sein.
Loren Pechtel
1

Wenn Sie große Datenmengen in Ihrer Anwendung speichern, wird Ihr Programm möglicherweise langsamer geladen und Sie setzen den Code möglicherweise einem Risiko aus, falls jemand mit den Binärdateien oder der ausführbaren Datei spielen könnte.

Auch wenn das Programm mehrmals bearbeitet wird, kann es sein, dass Sie Fehler einführen, indem Sie Zahlen versehentlich oder aufgrund eines Änderungsbefehls falsch eingeben.

Möglicherweise werden Sie in Zukunft gefragt, ob Sie Abfragen zu den Daten ausführen möchten, beispielsweise, ob Sie den Durchschnitt einer Spalte abfragen möchten. In diesem Fall müssen Sie Ihre Anwendung ändern und eine Methode hinzufügen, um jede Abfrage zu berechnen, die Ihr Benutzer aufruft Mit und dann mit allen Schritten fortfahren, um Ihren Code in die Produktion zu befördern. Das ist wirklich nicht gut.

Das Trennen von Daten und Code ist eine gute Vorgehensweise, insbesondere wenn die Daten groß sind.

Keine Chance
quelle