Czy podczas dostępu / manipulacji złożonymi danymi lepiej jest przechowywać je w wielu małych kawałkach lub w jednym dużym kawałku?

11

Tworzę aplikację internetową, która manipuluje dość złożonymi danymi: tabulatory.

    As a reference, guitar tabs look like this:
Eb|-------------------------------------------------------------------------|
Bb|-------------------------------------------------------------------------|
Gb|--5-5-5-5----------------------------------------------------------------|
Db|--5-5-5-5--3-3-3-3--7-7-7-7--5-5-5-5--2-2-2-2--3-3-3-3--2-2-2-2--5-5-5-5-|
Ab|--3-3-3-3--3-3-3-3--7-7-7-7--5-5-5-5--2-2-2-2--3-3-3-3--2-2-2-2--5-5-5-5-|
Eb|-----------1-1-1-1--5-5-5-5--3-3-3-3--0-0-0-0--1-1-1-1--0-0-0-0--3-3-3-3-|

Czy bardziej wydajne byłoby przechowywanie tych danych jako dużego fragmentu, czy też dzielenie ich i przechowywanie „na podstawie notatek”?

As a use case:
User changes first chord from:       to:
                         Eb|---   Eb|---
                         Bb|---   Bb|---
                         Gb|--5   Gb|--4
                         Db|--5   Db|--4
                         Ab|--3   Ab|--2
                         Eb|---   Eb|---

Jeśli przechowuję go jako blok, kod do manipulowania kartami musiałby być znacznie bardziej złożony. Jeśli zapiszę to notatka po notatce, dostęp do bazy danych będzie musiał być znacznie większy. Która metoda jest bardziej wydajna? Potencjalnie wielu użytkowników będzie modyfikować dane. Chcę najlepiej działającą aplikację internetową. Będę używać MySQL, jeśli w ogóle wpłynie to na odpowiedź.

Gabe Willard
źródło
2
Lepiej po co? Oszczędzasz miejsce? Moc procesora? IO Coś innego?
Oded
Cóż, to aplikacja internetowa. Wielu użytkowników może dość często modyfikować dane. Wyobrażam sobie, że wiele czynników, o których wspomniałeś, wpływa na to inaczej. Nie znam się tak dobrze na tych szczegółach; częściowo dlatego tu pytam.
Gabe Willard,
Jeśli nie wiesz, co optymalizujesz, jak możemy odpowiedzieć? Chodzi o to - najpierw zbuduj, jeśli masz określone problemy, a następnie zapytaj, jak je rozwiązać.
Oded
12
Czy nie projektujesz baz danych przed ich zbudowaniem? Moje pytanie dotyczy zaprojektowania bazy danych. Brak rozwiązywania problemów. Nie jestem jeszcze w fazie debugowania, a nawet gdybym tak był, przejdzie do StackOverflow, a nie programistów. Na najczęściej zadawane pytania: Programiści obejmują pojęcia algorytmów i struktury danych, wzorce projektowe, architekturę oprogramowania, inżynierię oprogramowania ...
Gabe Willard,
+1 bardzo interesujący problem i dobra ilustracja pracy przydatny przypadek użycia. Żałuję, że nie mam teraz dobrej wymówki, aby opracować aplikację na gitarę.
Evan Plaice

Odpowiedzi:

8

Liczba operacji będzie w obu przypadkach taka sama. Wykonujesz jedno zapytanie, aby uzyskać wszystkie akordy utworu, a następnie wykonujesz jedną aktualizację za każdym razem, gdy wprowadzana jest zmiana. Różnica polega na wielkości aktualizacji. Dzięki metodzie blokowania musisz zapisać cały utwór za każdym razem, gdy zmieniasz akord. Dzięki indywidualnej metodzie Twoje aktualizacje będą mniejsze i prawdopodobnie ogólnie bardziej wydajne, choć różnica może być nieznaczna.

Inną rzeczą do rozważenia jest to, że metoda notowania za notatką jest bardziej znormalizowana, co oznacza, że ​​będziesz mieć więcej opcji zapytań dostępnych po drodze, jeśli z niej skorzystasz. Na przykład początkujący mogą odfiltrowywać akordy, których nie znają podczas wyszukiwania utworu do nauki, lub możesz zezwolić na wyszukiwanie na podstawie akordów otwierających, jeśli ktoś nie zna tytułu utworu. Nawet jeśli nie planujesz teraz tych funkcji, zmiana bazy danych będzie bardzo uciążliwa, jeśli chcesz czegoś takiego później.

Karl Bielefeldt
źródło
5

Ogólnie rzecz biorąc, większa normalizacja jest dobra z kilku powodów:

  1. Mniejsze powielanie danych, co prowadzi do mniejszego rozmiaru fizycznej bazy danych.
  2. Lepsza integralność danych - możesz użyć kluczy obcych, aby wymusić określone wymagania.
  3. Prostszy kod aktualizacji, który zidentyfikowałeś.
  4. Bardziej indeksowalne trasy dostępu do podzbiorów danych.

Wady ( dobrze opisane tutaj ) obejmują:

  1. Normalizacja oszczędza miejsce, ale miejsce jest tanie.
  2. Normalizacja upraszcza aktualizacje, ale odczyty są częstsze.
  3. Wydajność jest ogólnie lepsza w przypadku mniej znormalizowanych schematów.

Sugerowałbym rozpoczęcie od bardziej znormalizowanego projektu i rozważenie denormalizacji, jeśli napotkasz problemy z wydajnością.

Mike Partridge
źródło
Z bazą tabulatorów gitary, prostota, spójność i integralność przewyższają wydajność. Więc wybrałbym najprostszy znormalizowany schemat, jaki mogłem wymyślić.
9000
2

Spraw, aby Twoje miejsce do przechowywania było najłatwiejsze w obsłudze i wystarczająco twarde, aby je zepsuć. Idź z rozsądnie znormalizowanym schematem. Jeśli to możliwe, zastosuj schemat, który nie wyklucza innych zastosowań niż te, które będą potrzebne w pierwszym wydaniu.

Jeśli wszystko, czego potrzebujesz, to wyświetlić tabulatory dla konkretnego utworu, możesz przechowywać wiele 6-krotek w DB zorientowanej na dokumenty (jak MongoDB), pobierając je jako jeden dokument.

W RDBMS zapisałbym go podobnie, w tabeli takiej jak ta:

table tab_column (
  song_id integer not null foreign key references song(id),
  ordinal integer not null, -- position in the tabulature
  s1 number(2), -- position on 1st string
  ...
  s6 number(2),
  primary key(song_id, ordinal)
)

RDBMS są dobre w prostych zapytaniach, takich jak te potrzebne do wyświetlenia utworu:

select * from tab_column
where song_id = :song_id
order by ordinal;

Za pomocą limiti offsetmożesz wyświetlać fragmenty utworu.

Później łatwo będzie połączyć tab_columnsię z tabelą, która zawiera listę nazwanych akordów, jeśli rozpoznasz akord.

Jest to prawdopodobnie najprostszy możliwy schemat; Zacznę od tego.

9000
źródło