Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Przechowywanie wiele kolumn numerycznych
Pyton_000
post 19.03.2018, 18:20:15
Post #1





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Temat dość prosty.

Tabela `measurements` z 98% kolumnami numerycznymi. Aktualnie ~33 kolumn.

Problem. Jak to przechowywać. Aktualnie zrobiłem PoC żeby działało. Teraz jak już działa to mogę się zająć optymalizacją.

Szukam jakiegoś sensownego rozwiązania...

1. Zostawić tak jak jest
+ czytelność
+ łatwość dodawania nowej kolumny

- szybko puchnie w szerz

2. Trzymanie w JSON
+ optymalizacja miejsca

- problem z dodaniem nowej kolumny

3. Zserializowany obiekt
+ łatwe trzymanie

- problem z dodaniem nowej kolumny


Biorę po 100zł z konta każdej drużyn i słucham Państwa... biggrin.gif
Go to the top of the page
+Quote Post
SmokAnalog
post 19.03.2018, 18:32:38
Post #2





Grupa: Zarejestrowani
Postów: 1 707
Pomógł: 266
Dołączył: 3.07.2012
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Takie poziome spuchnięte tabele to po prostu zły design, a jak numeryczne to już w ogóle kicha. Nie mam pojęcia co to jest PoC, ale dlaczego nie możesz po prostu dodawać tych cech jako rekordów?
Go to the top of the page
+Quote Post
Pyton_000
post 19.03.2018, 18:47:49
Post #3





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Proof of Concept wink.gif

To też rozważałem... I jest to kolejny pomysł.
Ja wiem że pakowanie w szerz to nie jest najlepszy pomysł dla tego słcuam głosu ludu smile.gif

A i kolejna uwaga to taka że zawsze będę pobierał wszytstkie wartości dla każdego wiersza.
Nie będę przeszukiwał/sortował/filtrował po tych parametrach. Kluczowych będzie tylko 3-4 reszta jako wartości pomiarowe per cecha.
Go to the top of the page
+Quote Post
phpion
post 21.03.2018, 07:03:20
Post #4





Grupa: Moderatorzy
Postów: 6 070
Pomógł: 860
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Ja bym zostawił jak jest. Zaczniesz normalizować i Ci wydajnościowo klęknie. Użyjesz JSONa i sie wyłożysz gdy będzie trzeba coś w nim znaleźć lub zmodyfikować.
Go to the top of the page
+Quote Post
Crozin
post 21.03.2018, 08:02:33
Post #5





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


> Ja wiem że pakowanie w szerz to nie jest najlepszy pomysł dla tego słcuam głosu ludu
Ale dlaczego? Jeżeli to są sensowne, różnorodne dane, co to jest w tym złego? Co to są dokładnie za dane? Trzymanie tego w formie jakieś zserializowanej tablicy, JSON-a itp. będzie najprawdopodobniej dużo mniej optymalne pod względem szybkości działania, objętości zajmowanego miejsca na dyskach/w pamięci, nie mówiąc już o jakimkolwiek wyszukiwaniu/filtrowaniu danych.
Go to the top of the page
+Quote Post
Pyton_000
post 21.03.2018, 08:42:35
Post #6





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Tak jak pisałęm są to dane numeryczne int, decimal.
Nie będzie wyszukiwania po tych danych, filtrowania ani innych operacji.
Zawsze pobierane są wszystkie te dane bo generowany jest z nich PDF i dodatkowo widok tabelaryczny.

Dla tego zastanawiałem się nad ew. optymalizacją ale jak pisałem problem potem może być w modyfikacji struktury tych danych tj, np. dodanie kolejnych kolumn.

Stąd pytanie czy ktoś ma jakiś fajny pomysł na to. Nie chcę dostawiać kolejnych potworków typu mongo czy elastic czy kij wie jeszcze bo za mało tego będzie na armaty. Rozwiązanie ma być proste z założenia
Go to the top of the page
+Quote Post
Crozin
post 21.03.2018, 08:59:07
Post #7





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Cytat
Tak jak pisałęm są to dane numeryczne int, decimal.
Jeżeli każda z tych ~30 wartości reprezentuje coś innego, coś unikalnego, coś co nie jest jakąś grupą/kolekcją/agregatem danych to każda z nich powinna być osobnym bytem - w przypadku bazy danych: kolumną.
Cytat
Nie będzie wyszukiwania po tych danych, filtrowania ani innych operacji.
Nie potrzebujesz wykonywać takich operacji teraz do osiągnięcia wymaganego efektu, ale nie zdziw się jak za 5 miesięcy, ktoś Cię poprosi o wycinek danych z marca, albo o ten raport za jakieś 5000 czy 6000 czegoś tam i najszybszym wykonaniem tego nowego zadania będzie napisanie prostej SQL-ki.
Cytat
Zawsze pobierane są wszystkie te dane bo generowany jest z nich PDF i dodatkowo widok tabelaryczny.
No i od tego mamy SELECT * .... ;-)

Cytat
Dla tego zastanawiałem się nad ew. optymalizacją [...]
Tu tkwi sendo problemu. smile.gif Masz w ogóle jakiś problem wydajnościowy? Co chciałbyś optymalizować? Szybkość dewelopmentu, przyszłe utrzymanie, szybkość pobierania danych, objętość danych na dyskach/w pamięci? Od razu podpowiem, że z sugerowanych "optymalizacji" wszystkie pogarszają wymienione przeze mnie aspekty.
Pamiętaj, że przedwczesna czy mikro optymalizacja to niemal zawsze złe rozwiązanie.
Go to the top of the page
+Quote Post
Pyton_000
post 21.03.2018, 09:36:45
Post #8





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Spokojnie, ja jestem z tych którzy piszą rozwiązanie w miaarę optymalne i nie bawią się w mikrooptymalizacje jeśli ich nie potrzeba.

Odpowiadając...

> Jeżeli każda z tych ~30 wartości reprezentuje coś innego, coś unikalnego, coś co nie jest jakąś grupą/kolekcją/agregatem danych to każda z nich powinna być osobnym bytem - w przypadku bazy danych: kolumną.
To są dane pomiarowe ciała człowieka, tj. obwody, składy masy ciała, tłuszczu itd. Dane są zbierane z wagi mierzącej skład ciała.

> Nie potrzebujesz wykonywać takich operacji teraz do osiągnięcia wymaganego efektu, ale nie zdziw się jak za 5 miesięcy, ktoś Cię poprosi o wycinek danych z marca, albo o ten raport za jakieś 5000 czy 6000 czegoś tam i najszybszym wykonaniem tego nowego zadania będzie napisanie prostej SQL-ki.
Jesli ktoś poprosi o wycinek danych to i tak muszą być pobrane wszystkie dane bo one są integralne i są robione obliczenia już później.

Co do jeszcze samej optymalizacji to chyba raczej o proces developmentu. Obecne rozwiązanie nie jest złe, jednak biorąc np. pod uwagę jak by wyglądało Entity w SF dla takiej tabeli to mnie głowa boli biggrin.gif
Go to the top of the page
+Quote Post
Crozin
post 21.03.2018, 11:30:53
Post #9





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Doctrine'owska encja faktycznie będzie miała wtedy 30 właściwości i niech je sobie ma, skoro ona ma na dobrą sprawę odzwierciedlać to co jest w bazie danych. Jeżeli część z tych danych można jakoś sensownie zgrupować też to możesz zrobić przy pomocy @Embeeded. Przecież encję i tak wykorzystuje się tylko na poziomie/w warstwie aplikacji przy bezpośredniej komunikacji ze źródłem danych, także zbyt często z tym potworkiem do czynienia mieć nie będziesz. smile.gif

Innymi słowy - mając 30 różnych danych (a wszystko wskazuje na to, że masz) musisz prędzej czy później się z nimi w kodzie spotkać i zdecydowanie lepiej mieć każdą z nich jawnie i klarownie zdefiniowaną.
Go to the top of the page
+Quote Post
Pyton_000
post 21.03.2018, 11:36:03
Post #10





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Myślałem jeszcze nad takim rozwiązaniem żeby wepchać je wszystkie w JSON do BD a potem zrobić mappera na to który będzie przez jakąś magiczną metodę pobierał wartości. więc w kodzie dalej będę mógł operować na pojedynczych wartościach.

Dodatkow w mapperze ustawić domyślną strukturę i przy pobieraniu zrobić merge, więc będę miał zawsze oczekiwaną strukturę nawet jeśli w BD będzie stara, a przy zapisie tylko wyjdzie update.

Zerknę jeszcze w Embedded bo może to mi trochę pomoże bo w sumie mogę zrobić kilka grup bo jest tam np. masa mięśni całkowita + 5 wartości z rozbiciem. Wtedy to ma sens.

Ten post edytował Pyton_000 21.03.2018, 11:37:35
Go to the top of the page
+Quote Post
SmokAnalog
post 21.03.2018, 12:35:29
Post #11





Grupa: Zarejestrowani
Postów: 1 707
Pomógł: 266
Dołączył: 3.07.2012
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Ja to zrozumiałem tak, że masz kolumny typu cośtam1, cośtam2, cośtam3. Gdyby tak było, wtedy byłby duży problem chociażby z wyszukiwaniem.

Jeśli to wszystko są faktycznie cechy ściśle związane z encją, to 30 kolumn będzie w porządku, chociaż wydaje mi się, że taka sytuacja jest rzadka. Przeważnie coś jednak stanowi osobną encję i jest np. wykorzystywane przez wiele innych rekordów.

Może się podziel strukturą tej tabeli?

Ten post edytował SmokAnalog 21.03.2018, 12:36:02
Go to the top of the page
+Quote Post
Pyton_000
post 21.03.2018, 13:33:22
Post #12





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


A na zdrowie smile.gif

  1. CREATE TABLE `measurements` (
  2. `id` int(10) UNSIGNED NOT NULL,
  3. `user_id` int(10) UNSIGNED NOT NULL,
  4. `m_c` smallint(5) UNSIGNED DEFAULT NULL,
  5. `m_ub` smallint(5) UNSIGNED DEFAULT NULL,
  6. `m_ar` smallint(5) UNSIGNED DEFAULT NULL,
  7. `m_al` smallint(5) UNSIGNED DEFAULT NULL,
  8. `m_w` smallint(5) UNSIGNED DEFAULT NULL,
  9. `m_t` smallint(5) UNSIGNED DEFAULT NULL,
  10. `m_h` smallint(5) UNSIGNED DEFAULT NULL,
  11. `m_thr` smallint(5) UNSIGNED DEFAULT NULL,
  12. `m_thl` smallint(5) UNSIGNED DEFAULT NULL,
  13. `m_car` smallint(5) UNSIGNED DEFAULT NULL,
  14. `m_cal` smallint(5) UNSIGNED DEFAULT NULL,
  15. `weight` decimal(5,1) UNSIGNED DEFAULT NULL,
  16. `height` tinyint(3) UNSIGNED DEFAULT NULL,
  17. `al` tinyint(3) UNSIGNED DEFAULT NULL,
  18. `fw` double(6,1) DEFAULT NULL,
  19. `far` double(6,1) DEFAULT NULL,
  20. `fal` double(6,1) DEFAULT NULL,
  21. `ffr` double(6,1) DEFAULT NULL,
  22. `frf` double(6,1) DEFAULT NULL,
  23. `ft` double(6,1) DEFAULT NULL,
  24. `mw` double(6,1) DEFAULT NULL,
  25. `mar` double(6,1) DEFAULT NULL,
  26. `mal` double(6,1) DEFAULT NULL,
  27. `mfr` double(6,1) DEFAULT NULL,
  28. `mfl` double(6,1) DEFAULT NULL,
  29. `mt` double(6,1) DEFAULT NULL,
  30. `bw` double(6,1) DEFAULT NULL,
  31. `if` tinyint(3) UNSIGNED DEFAULT NULL,
  32. `rd` smallint(5) UNSIGNED DEFAULT NULL,
  33. `ra` tinyint(3) UNSIGNED DEFAULT NULL,
  34. `ww` double(6,1) DEFAULT NULL,
  35. `measurement_date` date NOT NULL,
  36. `created_at` timestamp NULL DEFAULT NULL,
  37. `updated_at` timestamp NULL DEFAULT NULL,
  38. `expected_weight` tinyint(3) UNSIGNED DEFAULT NULL,
  39. `activity_level` tinyint(3) UNSIGNED NOT NULL DEFAULT '1'
  40. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


To jest aktualna struktura zrobiona na szybko jako proof of concept.
Go to the top of the page
+Quote Post
Crozin
post 21.03.2018, 16:17:24
Post #13





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Wepchasz to w JSON-a: będzie wolniejsze pod każdym względem: czasu zapisu, odczytu, modyfikacji, miejsca na dysku, czasu odczytu/zapisu przez PHP-a, wprowadzania zmian (będziesz musiał jak sam zaznaczyłeś pisać jakieś magiczne mappery/mergery) czyli ogólnie rzecz biorąc: dewelopmentu. Po co to wszystko? Jeżeli masz zasób, który składa się z relatywnie dużej liczby właściwości... no OK, z reguły jest to oznaka czegoś złego, ale tutaj nie wydaje się tu być przypadkiem. Tylko zlituj się sam nad sobą i stosuj pełne nazwy dla kolumn - to nie lata 80 by długość tego typu nazw miała dla czegoś znaczenie.
Go to the top of the page
+Quote Post
SmokAnalog
post 21.03.2018, 16:45:50
Post #14





Grupa: Zarejestrowani
Postów: 1 707
Pomógł: 266
Dołączył: 3.07.2012
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Moja poprzednia sugestia z cechami jako rekordami może nie jest tutaj najlepsza, bo zestaw cech jest chyba stały. Albo względnie pełny pomiar, albo wcale.

Ale pomyślałem sobie o czymś. Czy użytkownik pojawia się w bazie zawsze z pomiarami? Pewnie nie, bo kolumny są nullable. Dlatego rozważyłbym wstawienie pomiarów do osobnej tabeli, z relacją 1:1 z użytkownikiem. Kosztem tego będzie oczywiście konieczność JOIN-owania, które jednak dla wydajności nie ma praktycznie żadnego znaczenia, ale już do pisania zapytań ma. Jest jednak kilka zalet takiego rozwiązania:

  • Możesz w bardziej jednoznaczny sposób określić czy dokonano pomiaru, bo rekord pomiaru albo będzie istniał, albo nie. W chwili obecnej oczywiście możesz to zrobić sprawdzając którąś kolumnę (pewnie datę pomiaru), ale nie jest to aż tak jednoznaczne jak istnienie rekordu. Pomiar mógł teoretycznie być zrobiony nie wiadomo kiedy.
  • O ile poprzedni argument jest trochę na siłę, tak kolejny jest już poważniejszy. Możesz na poziomie bazy ustalić które kolumny są niezbędne do pomiaru. Zamiast mieć wszystkie nullable, będziesz mógł sobie wybrać niezbędne elementy pomiaru. W chwili obecnej też możesz, ale pomiar musi się pojawić od razu z użytkownikiem, a pewnie w praktyce to nie jest takie naturalne.


Podsumowując, czasami warto rozważyć relację 1:1, bo odrębny byt jednak pozwala na więcej kontroli nad danymi.
Go to the top of the page
+Quote Post
Pyton_000
post 21.03.2018, 18:51:14
Post #15





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Cytat(Crozin @ 21.03.2018, 16:17:24 ) *
Tylko zlituj się sam nad sobą i stosuj pełne nazwy dla kolumn - to nie lata 80 by długość tego typu nazw miała dla czegoś znaczenie.

Uwierz mi że dla mnie ma wink.gif Mam dane które importuję i po prostu wrzucam do bazy, nie bawię się w mapowanie kolumna -> nazwa.
Czytam z csv i kolumnami wrzucam dane. Poza tym weź pisz ciągle potem bone_weight_foot_right, bone_weight_foot_left biggrin.gif

@Smoku co do Twojej wypowiedzi. Pomiary są dokonywane i maszynowo i ręcznie a potem razem wędruje do bazy. Ale tak czytam i czytam to co napisałes i nie za bardzo rozwija się to w mojej głowie. Nie za bardzo rozumiem co miałes na myśli pisząc o relacji 1:1 z userem. Pomiarów będzie wiele per user więc 1:n
Go to the top of the page
+Quote Post
phpion
post 21.03.2018, 19:20:12
Post #16





Grupa: Moderatorzy
Postów: 6 070
Pomógł: 860
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Może jednak iść w stronę normalizacji? Zrób sobie słownik parametrów:
id, nazwa (m_c, m_ub itd)
i tabelę dla parametrów pomiarów:
id_pomiaru, id_parametru, wartość
Minus taki, że kolumna wartość musiałaby posiadać „wspólny” typ danych czyli u Ciebie pewnie decimal(6,1). Nie wiem jak zapisujesz dane do bazy ale kluczem głównym słownika pomiarów wcale nie musi być sztuczna wartość 1, 2, 3... a właśnie m_c, m_ub (wówczas w polu nazwa masz słowną nazwę parametru). Może właśnie to będzie najlepszym rozwiązaniem?
Go to the top of the page
+Quote Post
SmokAnalog
post 21.03.2018, 19:24:05
Post #17





Grupa: Zarejestrowani
Postów: 1 707
Pomógł: 266
Dołączył: 3.07.2012
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Pomiarów jest więcej i dałeś po jednej kolumnie per jednostka pomiaru? Dziwne rozwiązanie.

Czy te pomiary są zupełnie niezależne od siebie? Tzn. czy może być pomiar jednej rzeczy bez innej rzeczy? I czy są jakieś grupy pomiarów, czyli np. dwie cechy (lub więcej) zawsze będą razem mierzone, nigdy osobno?
Go to the top of the page
+Quote Post
phpion
post 21.03.2018, 19:36:29
Post #18





Grupa: Moderatorzy
Postów: 6 070
Pomógł: 860
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Cytat(SmokAnalog @ 21.03.2018, 19:24:05 ) *
Pomiarów jest więcej i dałeś po jednej kolumnie per jednostka pomiaru? Dziwne rozwiązanie.

To pytanie do mnie?
Go to the top of the page
+Quote Post
Pyton_000
post 21.03.2018, 19:51:01
Post #19





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Pytanie do mnie wink.gif

@phpion to też jest jakieś rozwiązanie, nie uzależniam się od ilości parametrów, ale właśnie wspólny typ który jak zauważyłeś mógłby być DECIMAL(6,1)

@Smoku

Z tych danych można wyodrębnić 2 grupy po 6 cech i one zawsze będą razem bo to maszynowy pomiar całkowity + rozbicie.
I co masz na mysli mówiąc:

>> Pomiarów jest więcej i dałeś po jednej kolumnie per jednostka pomiaru? Dziwne rozwiązanie.
Go to the top of the page
+Quote Post
SmokAnalog
post 21.03.2018, 21:13:37
Post #20





Grupa: Zarejestrowani
Postów: 1 707
Pomógł: 266
Dołączył: 3.07.2012
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Wybacz, nie doczytałem. Myślałem, że przechowujesz te pomiary w tabli `users`. W takim razie może rozdzielić te tabele na zestawy pomiarów?
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 28.03.2024 - 22:02