Praktyczny sposób na przechowywanie „rozsądnie dużej” ilości danych, które prawie nigdy się nie zmieniają?

14

Pomyśl w kategoriach wstępnie obliczonych tabel odnośników lub czegoś takiego. W którym momencie bardziej sensowne jest używanie bazy danych zamiast twardych wartości w mojej aplikacji? Wartości nie zmienią się i są ładnie oddzielone od deweloperów konserwacji. 100 wartości, 1k, 10k, 100k? Chcę zapisać około 40 000 wartości. W tej chwili jest to generowana maszynowo switchinstrukcja (z której VS2010 jest niezadowolony).

edytować:

Jeśli ktoś jest ciekawy, oto jak do tego doszedłem: moje dane były przechowywane w dwóch 100-elementowych tablicach pływakowych, więc to właśnie zrobiłem. Generowanie danych zajęło około 20 sekund, więc zrobiłem to raz i zserializowałem je do zasobu osadzonego za pomocą BinaryFormatter. Rozpakowanie danych zajmuje około 5 milisekund podczas uruchamiania aplikacji i przewyższa implementację bazy danych, którą zastępowałem (te zapisane na stałe wartości były tam wcześniej przechowywane) o prawie 45 000x.

Bryan Boettcher
źródło

Odpowiedzi:

5

Sugeruję, aby przechowywać dane w tabeli pliku lub bazy danych. Jeśli prędkość nie stanowi problemu, przeprowadź zapytanie do pliku lub bazy danych (baza danych jest lepsza) w czasie wykonywania. Jeśli pamięć nie stanowi problemu, ale potrzebujesz pewnej prędkości, załaduj dane do pamięci po uruchomieniu programu. W języku C # można użyć i tablicować, wyświetlać lub (najlepsza opcja) tablicę skrótów i mieć metodę zwracania potrzebnych danych w czasie wykonywania (tj. GetDataValue (string keyToValue)).

Radziłbym nie używać instrukcji switch, ponieważ byłoby to bardzo trudne w utrzymaniu i spowodowałoby duży ślad exe.

Tabela skrótów, np. Http://support.microsoft.com/kb/309357

Adam F.
źródło
To właśnie zrobiłem: sprawdź mój zaktualizowany post.
Bryan Boettcher
1
+1 za sugestię bazy danych. Bazy danych są przeznaczone do przechowywania dużych ilości danych i umożliwiają bardzo szybkie ich pobieranie.
NoChance,
Zobacz stackoverflow.com/questions/301371/..., dlaczego lepiej jest używać do tego słownika niż tablicy hashtable. YMMV
Chris McKee
6

Osobiście jestem w stanie przechowywać dowolną ilość danych, zakodowanych na stałe w aplikacji, dopóki nie będzie potrzeby poprawiania ich dla jednego konkretnego wdrożenia lub poprawki.

Jednak przechowywanie i uzyskiwanie dostępu do danych przy użyciu instrukcji przełączania C # jest raczej złą praktyką, ponieważ w ściśle powiązanych modelach przechowywania danych i dostępu do danych implikuje tylko jedną metodę dostępu do metody (według parametru przełącznika).

Wolałbym przechowywać dane w Hashtable lub Dictionary i zapewnić osobne klasy do pobierania danych i jednorazowego zapełniania słowników przeglądowych.

Niedawno uznałem za dogodne wdrożenie małej DSL do określania reguł biznesowych ( płynny interfejs dla SiteMap lub kalkulator podatkowy, sprawdzanie pytań metodą „oblicz” w celu ustalenia reguł), a następnie udostępnienie oddzielnego obiektu do zapytania o te reguły. Ta technika miałaby zastosowanie również w przypadku scenariusza przełączania.

Jedną z miłych zalet takiego rozkładu jest to, że możesz zaimplementować w swoich danych wiele widoków, bez dotykania obiektu blob linii XXXk, który definiuje te dane.

Valera Kolupaev
źródło
Rozszerzyłem odpowiedź z kilkoma przykładami.
Valera Kolupaev
2

Oświadczenie o zmianie linii na 40 tys. Jest nieco wątpliwe. Zakładam, że nadal musisz wykonywać operacje zapytania, prawda? Próbowałeś enkapsulować dane? Następnie użyj LINQ do wykonania operacji zapytania na kolekcji w celu przetestowania wydajności. Uzyskaj konkretne czasy, uruchamiając testy jednostkowe z zegarem takim jak StopWatch . Jeśli uważasz, że to może po prostu działać. Sprawdź, czy wydajność jest akceptowalna dla użytkowników.

P.Brian.Mackey
źródło
2

Miałem takie wymagania dwa razy. Aplikacje zostały zaprojektowane tak, aby były samodzielne i nie wymagały konfiguracji / dostępu do bazy danych. W obu przypadkach użyłem plików XML do przechowywania danych. W pierwszym, który był na platformie 2.0, do wyszukiwania danych używałem wywołań XML w starym stylu. W nowszym, w frameworku 3.5, użyłem LINQ to XML, aby znaleźć to, czego potrzebowałem. W obu przypadkach dostęp do danych został zamknięty w klasach.

jfrankcarr
źródło
1

Kluczową kwestią jest upewnienie się, że interfejs publiczny zawiera implementację - ale to nie jest twoje pytanie i nie ma powodu, aby sądzić, że tego nie zrobiłeś. Poza tym to tylko kwestia wydajności vs żalu (a różnice w wydajności mogą nie być warte dbania). Jako praktyczne rozwiązanie problemu VS 2010 można zawsze podzielić instrukcję case na hierarchię instrukcji case - najwyższy poziom może wywołać jedną z 10 innych metod, na przykład każdą z instrukcją case zawierającą 4000 przypadków. Możesz umieścić każdą z 10 we własnym pliku, jeśli musisz. Trochę brzydka, ale i tak generujesz kod.

Jeśli chodzi o liczbę przełączającą się na DB, to tylko wtedy, gdy nieużywanie DB staje się problemem.

psr
źródło
Doceniam myśl, że mój interfejs zawiera implementację: z pewnością tak. Funkcjonalność jest ujawniana za pomocą GetValuesForInputmetody -type, a moje masowe stwierdzenie jest ukryte w implementacji.
Bryan Boettcher
1

Możesz użyć czegoś takiego jak SQL Compact. Umieść dane w tabeli i pozostaw plik DB w projekcie. Tabele lepiej nadają się do tej ilości danych niż instrukcja switch.

Morgan Herlocker
źródło
1

Myślę, że kluczowym słowem jest „prawie”

Jeśli dane nigdy się nie zmieniają - na przykład wstępnie obliczone wartości matematyczne, stałe kolorów i tym podobne - to upewnij się, że dopóki rozmiar jest możliwy do zarządzania, zachowaj go w kodzie. Należy pamiętać, że jeśli wydajność stanowi problem, instrukcje case / switch będą bardzo wolne w porównaniu do innych opcji.

Jeśli dane prawie nigdy się nie zmieniają - na przykład numery kierunkowe telefonu, granice państwowe i tym podobne - zapewne postaram się w jakiś sposób przechowywać dane na zewnątrz. Szczególnie, jeśli zaczęło być więcej niż kilkadziesiąt wartości.

Grandmaster B.
źródło
1
To zależy od tego, jak dobry jest kompilator. Deklaracja przypadku w Delphi może być bardzo wydajna.
Loren Pechtel
1

Jeśli przechowujesz duże ilości danych w aplikacji, wówczas program może ładować się wolniej i możesz narazić kod na ryzyko, na wypadek gdyby ktoś mógł grać z plikami binarnymi lub plikiem wykonywalnym.

Ponadto, jeśli program jest edytowany wiele razy, kto wie, być może możesz wprowadzić błędy, wpisując cyfry przez pomyłkę lub w wyniku polecenia zmiany.

Być może w przyszłości ktoś poprosi o uruchomienie zapytań o dane, powiedzmy, że ktoś może poprosić o średnią kolumny, w takim przypadku będziesz musiał zmienić aplikację i dodać metodę obliczania każdego zapytania, które pojawi się użytkownik za pomocą, a następnie wykonaj wszystkie kroki, aby promować swój kod do wersji produkcyjnej. To naprawdę nie jest dobre.

Oddzielanie danych i kodu jest dobrą praktyką, szczególnie jeśli dane są duże.

Bez szans
źródło