[SQLite] Projektowanie bazy danych - seria w kolumnach czy w wierszach ?

[SQLite] Projektowanie bazy danych - seria w kolumnach czy w wierszach ?
tom_85
  • Rejestracja:prawie 19 lat
  • Ostatnio:ponad 8 lat
0

Witam!

piszę moduł do aplikacji obliczeniowej która będzie wykorzystywać dużo danych pomiarowych. Będą do np. pomiary co godzinę lub częściej przez cały rok. Pomiary te mogą zaczynać się oraz kończyć w różnym czasie. Nie wiem jak zaprojektować poprawnie tabele w bazie danych (SQLite) aby wszystko chodziło jak najszybciej bo szybkość jest bardzo ważna. Moja koncepcja jest taka (dwie tabele):

TabelaSeriePomiarow(identyfikator serii, data rozpoczęcia pomiarów, ilość pomiarów)

TabelaPomiary(identyfikator serii - nazwa wiersza?, pomiar 1, pomiar 2, ... pomiar n)

tylko jak bym sobie tego nie wymyślił to i tak wiem że coś źle robię, coś mi ciągle nie pasuje. Dlatego pytam Was: jak to ogarnąć żeby było dobrze?

Co do tabeli TabelaSeriePomiarow to zastanawiam się jeszcze nad jedną rzeczą... otóż czy jest sens tworzyć w tej tabeli dodatkowe pola opisujące np. maksymalną wartość lub średnią z serii pomiarów? czy za każdym razem gdy taka wartość jest mi potrzebna to pobierać całą serię pomiarów i obliczać te wartości?

edytowany 1x, ostatnio: tom_85
Marcin.Miga
  • Rejestracja:prawie 17 lat
  • Ostatnio:około 9 godzin
  • Postów:2792
1

Jeśli serie umieścisz w kolumnach, to narobisz sobie problemów. Np. wyliczeniem średniej z serii będziesz musiał się zajmować sam, bo żaden mechanizm SQLowy nie da rady.
TabelaPomiary(
Id integer not null primary key,
idSerii integer not null,
numerPomiaru integer,
wartosc ...
)
tak to z grubsza powinno wygladać.

tom_85
  • Rejestracja:prawie 19 lat
  • Ostatnio:ponad 8 lat
0

heh tydzień bym myślał i bym nie wymyślił...

Marcin.Miga jedno spojrzenie na to co napisałeś i od razu wiem że to jest to :) tylko zamiast numer pomiaru będzie data pomiaru... no chyba że ktoś podpowie coś jeszcze lepszego...

Kolejne pytanie: czy przy (mniej więcej) takiej organizacji tabeli Pomiary jak napisał Marcin.Miga jest sens robić tabele SeriePomiarów w której były by np. data rozpoczęcia pomiarów, średnia wartość pomiarów, maksymalna wartość pomiarów, ilość pomiarów? czy za każdym razem lepiej "wyłuskiwać" sobie te dane z tabeli pomiary?

edytowany 1x, ostatnio: tom_85
Marcin.Miga
  • Rejestracja:prawie 17 lat
  • Ostatnio:około 9 godzin
  • Postów:2792
1

Jest sens. Przy dużej ilości pomiarów i/albo dużej ilości w jednej serii odczytanie pojedynczego rekordu jest dużo szybsze niż wyliczenie tego z poszczególnych pomiarów.

enix
  • Rejestracja:prawie 13 lat
  • Ostatnio:około 12 lat
  • Postów:23
0

Jak najbardziej jest sens. Dzięki temu czas potrzebny na zagregowanie wszystkich pomiarów będzie "zużywany" po kawałku w odniesieniu do danej serii pomiarowej. Mając zagregowane dane o całych seriach, dalsze raportowanie, agregacja będą już o wiele szybsze. Oczywiście wszystko zależy od skali i ilości danych.

tom_85 napisał(a):

heh tydzień bym myślał i bym nie wymyślił...

Marcin.Miga jedno spojrzenie na to co napisałeś i od razu wiem że to jest to :) tylko zamiast numer pomiaru będzie data pomiaru... no chyba że ktoś podpowie coś jeszcze lepszego...

Kolejne pytanie: czy przy (mniej więcej) takiej organizacji tabeli Pomiary jak napisał Marcin.Miga jest sens robić tabele SeriePomiarów w której były by np. data rozpoczęcia pomiarów, średnia wartość pomiarów, maksymalna wartość pomiarów, ilość pomiarów? czy za każdym razem lepiej "wyłuskiwać" sobie te dane z tabeli pomiary?

bogdans
I to pisze wyznawca poglądu, że redundancja danych nigdy nie jest wskazana. Ciekawe.
LE
  • Rejestracja:prawie 13 lat
  • Ostatnio:prawie 12 lat
  • Postów:10
0

Oczywiscie ze jest sens aby to wszystko rozbic na tabele. Do tabeli gdzie bedziesz wpisywac transakcje po prostu dodasz kolumne do ktorej bedziesz wpisywac date. Mozesz rowniesz uzyc trigera do automatyczego zapisu czasu wpisania rekordu (pomiaru) np: DATETIME('NOW')

tom_85
  • Rejestracja:prawie 19 lat
  • Ostatnio:ponad 8 lat
0

aby zakończyć wątek napiszę co postanowiono :P

w bazie znajdą się dwie tabele odpowiedzialne za pomiary:
1 - tabela zawierająca zbiorcze informację o każdej z serii pomiarów o budowie mniej więcej takiej:
TabelaSeriePomiarów(id serii, maksimum serii, średnia serii, data rozpoczęcia pomiarów, ilość pomiarów w serii)
2 - tabela zawierająca pojedyncze pomiary każdej z serii o budowie mniej więcej takiej:
TabelaPomiary(id pomiaru, id serii, data pomiaru, wartość pomiaru)

Wydaje mi się że na chwilę obecną jest to najlepsze rozwiązanie (nie mam zbyt dużo czasu na napisanie tego modułu) jednak w przyszłości gdy tylko znajdę "wolną chwilkę" to przyjrzę się nierelacyjnym bazom danych bo bardzo możliwe że do tego celu było by to lepsze rozwiązanie niż SQLite :-) Tak że na chwilę obecną problem uważam za rozwiązany!

Dziękuję za pomoc - bez Was nie dałbym rady!

agilob
  • Rejestracja:prawie 13 lat
  • Ostatnio:ponad 8 lat
  • Postów:148
0

Jeśli system obliczeń ma działać bez przerwy, może warto trzymać dane w pamięci RAM i co jakiś czas zapisywać dane do bazy, wtedy podejmujesz ryzyko, że w czasie awarii (brak prądu) tracisz część danych, które nie były zapisane. Popatrz też, że SQLite możesz kompilować z wieloma flagami, które przyspieszają bazę danych, w operowaniu masz polecenia PRAGMA, w których możesz ustawiać wielkość strony, ilość trzymanego cache itp. Wtedy musisz sobie przeliczyć ile RAM możesz używać, ile danych będziesz trzymał. Kilka takich "trickow" i możesz kilkuset-krotnie przyspieszyć operacje na SQLite3.


Kiedyś miałem sen... że wszyscy ludzie zaczną używać tagów <code> i czytać błędy kompilatora...
tom_85
  • Rejestracja:prawie 19 lat
  • Ostatnio:ponad 8 lat
0
agilob napisał(a):

(...) Popatrz też, że SQLite możesz kompilować z wieloma flagami, które przyspieszają bazę danych (...) Kilka takich "trickow" i możesz kilkuset-krotnie przyspieszyć operacje na SQLite3.

poszukam, poczytam jak masz jakieś ciekawe linki na ten temat pod ręką to ślicznie poproszę :-)

obliczenia będą uruchamiane bardzo, bardzo, bardzo rzadko ale podczas obliczeń będzie (może być) potrzebnych tyle danych że właśnie dlatego postanowiłem użyć bazy danych zamiast trzymać dane w pamięci.

edytowany 1x, ostatnio: tom_85
agilob
Odezwałem się tutaj bo sam bawiłem się bazą danych, która co dzień rosła o 30MB, a jak zacząłem miała 710MB, zacząłem szukać na temat optymalizacji SQLite3, mogę zrobić kryptoreklamę swojego bloga: http://b.agilobable.pl/przyspieszanie-sqlite3/ jest to tłumaczenie wszelkich porad jakie znalazłem na stackexchange i w dokumentacji SQLite3
tom_85
Na Twoim blogu jest kilka porad jak przyśpieszyć SQLite ale ja za bardzo nie mogę sobie pozwolić na utratę danych a Twoje propozycje w większości tym właśnie grożą :) Wole żeby wszystko działało troszkę wolniej ale stabilniej. P.S. Bardzo fajny blog i przydatny ale nie do tego co akurat potrzebuję :)
LE
  • Rejestracja:prawie 13 lat
  • Ostatnio:prawie 12 lat
  • Postów:10
0

Nie obawiaj się wielkości bazy. Zapisywania do pamięci ma tylko ta wadę ze można bardzo łatwo stracić dane. Jest to na pewno szybsze ale przy dobrym rozpisaniu bazy nie będziesz miał z tym problemu.
Używając wrappera na pewno będzie to szybkie. ( robię zapis 15.000 rekordów danych klientów z pliku ASCII do bazy SQLite w mniej niż 2 sekundy )
Podczas pierwszej próby miałem czas 28 sekund. Po prostu trzeba się troszeczkę z tym pomeczyc a wyniki mogą być imponujące.

tom_85
  • Rejestracja:prawie 19 lat
  • Ostatnio:ponad 8 lat
0

a co mi tam... pociągnę temat dalej bo dobrze mi się z Wami pisze :P

piszę w Delphi .Net 1.1 i do komunikacji z SQLite chciałem użyć ODBC (System.Data.Odbc) co o tym myślicie? dobre rozwiązanie? czy istnieje lepsze, szybsze, bardziej uniwersalne dla Delphi .net 1.1?

lechk napisał(a):

Nie obawiaj się wielkości bazy.
W aplikacji którą rozwijam mogą pojawić się schematy np. z tysiącem elementów z których każdy będzie miał pomiary przez rok co 15 minut co daje dość spory rozmiar. W pamięci tego raczej nie ulokuje...

Obecnie męczę się z napisaniem jakiegoś fajnego interfejsu do baz danych aby w przyszłości rozszerzyć jeszcze funkcjonalność aplikacji o korzystanie z innych baz danych.

Marcin.Miga
100036524*4=35040000. załóżmy, że wielkość struktury (pojedynczego rekordu) masz 12 bajtów: IDPomiaru (4 bajty) , ID (4 bajty) i wartość (4 bajty) to daje ci zawrotną liczbę 420480000 czyli ok. 400 megabajtów... Naprawdę tak dużo?
Marcin.Miga
A ODBC jest najdłuższą z możliwych dróg.
tom_85
no to nie jest jakaś niewyobrażalna ilość ale: po 1: może być tego więcej, po 2: sam schemat z elementami który też jest przetrzymywany w pamięci też sporo zajmuje po 3: dolicz sobie na każdym z 1000 elementów jeszcze dodatkowe miejsce na wyniki obliczeń czyli kolejne takie długie wektory ponieważ wyniki mam wyświetlać jako grafik który można przeglądać dzień po dniu :) P.S. robiłem już podobne testy i na prawdę gdyby załadować to wszystko do pamięci to komputer chodzi jak stara k... - takie są fakty że bez bazy danych będzie ciężko.
LE
  • Rejestracja:prawie 13 lat
  • Ostatnio:prawie 12 lat
  • Postów:10
0

Ja pracuje na wxWidgets c++ i SQLite ( przez wrapper ). A co do rekordów to gdy bedżie tego aż tak dużo , może lepiej by podzielić te table np na rok?
Myśle ze na pewno znajdziesz na to sposób.

tom_85
  • Rejestracja:prawie 19 lat
  • Ostatnio:ponad 8 lat
0

A ODBC jest najdłuższą z możliwych dróg.

To co zamiast ODBC tak żeby działało z SQLite pod Delphi .Net 1.1 i było darmowe?

i dlaczego ODBC jest najdłuższą z możliwych dróg ?

edytowany 1x, ostatnio: tom_85
Marcin.Miga
  • Rejestracja:prawie 17 lat
  • Ostatnio:około 9 godzin
  • Postów:2792
0
tom_85
  • Rejestracja:prawie 19 lat
  • Ostatnio:ponad 8 lat
0

http://system.data.sqlite.org/index.html/doc/trunk/www/faq.wiki#q3 :

(3) What versions of .NET Framework are supported?

The .NET Framework 2.0 SP2 (or higher) for the System.Data.SQLite assembly.

The .NET Framework 3.5 SP1 (or higher) for the System.Data.SQLite.Linq assembly.

All sub-projects are fully supported with the .NET Framework 4.0.

z tego co widzę to .net 1.1 niestety nie jest wspierany :/

jakieś inne propozycje?

edytowany 2x, ostatnio: tom_85
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)