Mamy kilkanaście produktów. Produkty mają cechy wspólne jak cena, typ ale także charakterystyczne dla danego produktu. Wszystkie wspólne cechy chcielibysmy zapisać w jednej tabeli. Natomiast te charakterystyczne w osobnych lub w jednej.
Jaka tutaj jest najlepsza praktyka zapisywania tych dodatkowych cech, aby łatwo i w miare wydajnie można był potem po nich relizowac także wyszukiwanie?
Przykładowo jeśli była by to wspólna tabela to miała by ona strukture:
id_produktu, nazwa_pola, wartość_pola
Czy takie podejście jest poprawne, czy może warto zastosować inne? Czy może w przypadku wspólnej tabeli użyć polymorphic association. A może raczej te dane powinny być w osobnych tabelach ?
Może Postgresowy hstore będzie pomocny: http://schneems.com/post/19298469372/you-got-nosql-in-my-postgres-using-hstore-in-rails https://github.com/softa/activerecord-postgres-hstore. Również to może się przydać: http://kylebanker.com/blog/2010/04/30/mongodb-and-ecommerce/
Projekt jest dosyć pilny, narazie chcielibyśmy się trzymać dobrze nam znanych i sprawdzonych rzeczy, wiec w gre wchodzi tylko MySQL.
Przepraszam jeśli niezbyt dokładnie sprecyzowałem tabele. Nie będzie to sklep gdzie typów produktów będzie pare tysiecy jak w allegro czy coś takiego. Tych danych, które rozróżniają produkty, specyficznych będzie 10 do 20 typów. Samych produktów już w bazie może być już dużo więcej, tysiące. Tak że zależy mi także żeby to się w miarę zgrabnie przeszukiwało, zarówno po tych danych wspólnych jak i tych specyficznych. Kwestia z pierwszego postu jak te dane specyficzne rozmieścić w bazie/relacjach.
Seriously? Mysql?
Ja rozumiem, gdyby ktoś krzyczał - “bierz mongo!!!1111” - ale używanie mysqla to masochizm Chyba, że w grę wchodzą replikacje - wiem, że kiedyś w postgresie był z tym problem, nie wiem jak jest teraz.
Seriously? Mysql?
Ja rozumiem, gdyby ktoś krzyczał - “bierz mongo!!!1111” - ale używanie mysqla to masochizm Chyba, że w grę wchodzą replikacje - wiem, że kiedyś w postgresie był z tym problem, nie wiem jak jest teraz.[/quote]
Popieram, jedyna bardziej odczuwalna różnica między myslem i postgresem jest działanie group by - mysql nie jest tutaj zgodny ze standardem SQL i pozwala w SELECT ustawić pola, które nie są agregacjami ani nie są w GROUP BY. Co przy prostych przypadkach może być wygodne, ale może też prowadzić do subtelnych błędów.
Seriously? Mysql?
Ja rozumiem, gdyby ktoś krzyczał - “bierz mongo!!!1111” - ale używanie mysqla to masochizm Chyba, że w grę wchodzą replikacje - wiem, że kiedyś w postgresie był z tym problem, nie wiem jak jest teraz.[/quote]
Popieram, jedyna bardziej odczuwalna różnica między myslem i postgresem jest działanie group by - mysql nie jest tutaj zgodny ze standardem SQL i pozwala w SELECT ustawić pola, które nie są agregacjami ani nie są w GROUP BY. Co przy prostych przypadkach może być wygodne, ale może też prowadzić do subtelnych błędów.[/quote]
A patrząc w drugą stronę postgres zyskuje coraz więcej fajnych rzeczy typu arrays (ostatnio w projekcie uratowało mnie to przed lezieniem pod górkę), czy wspomniany hstore. Jeśli ktoś pisze swoje własne funkcje to w wersji 9 jest kilka fajnych zmian w PL/SQL.
A jak wygląda obecnie sprawa dostępności narzędzi do ERD i odpowiednika Query Browsera dla Postgresa?
Rozumiem ze Postgress jest lepszy od MySQL i chętnie przy kolejnym projekcie go użyje, ale obecny projekt jest dosyć pilny i nie mam za bardzo czasu na wdrażanie się w Postgressa. Dlatego chciałbym potwierdzić, który sposób w opisanych w pierwszym i trzecim poście jest lepszy. Czy coś ala metoda słownikowa, czy może osobne tabele, może coś z polimorfizmem albo coś innego ?
Aha, co ważne zarówno dane wspólne, jak i specyficzne będą przeszukiwane Sphinxem.
[quote=Artur79]Rozumiem ze Postgress jest lepszy od MySQL i chętnie przy kolejnym projekcie go użyje, ale obecny projekt jest dosyć pilny i nie mam za bardzo czasu na wdrażanie się w Postgressa. Dlatego chciałbym potwierdzić, który sposób w opisanych w pierwszym i trzecim poście jest lepszy. Czy coś ala metoda słownikowa, czy może osobne tabele, może coś z polimorfizmem albo coś innego ?
Aha, co ważne zarówno dane wspólne, jak i specyficzne będą przeszukiwane Sphinxem.[/quote]
Jeżeli chodzi o sphinxa, to stosunkowo łatwo można w nim indeksować różne połączone tabele (przy JOINach tylko trochę dłużej się indeksuje), więc tutaj nie ma żadnego znaczenia.
Z tych rozwiązań, które podałeś wszystkie mają jakieś wady, przy czym polimorfizm ma tą poważną wadę, że automatycznie tracisz możliwość sprawdzania integralności danych na poziomie bazy. Dlatego jeżeli zależy Ci na tym, to lepiej chyba być mniej DRY i zrobić 2 osobne tabele. Jeżeli nie, to polimorfizm pewnie da radę, ale od razu mówię, że zbyt intensywnie nigdy tego nie używałem (z reguły to były jakieś mało ważne dane z tego co pamiętam). W każdym razie pytanie brzmi czy wolisz mieć to zrobione “po bożemy” z punktu widzenia bazy danych czy wolisz być DRY.
Możesz jeszcze zrobić to w drugą stronę, tzn. żeby w produkcie był klucz do tych danych, które są wspólne. Wydaje mi się, że wtedy musisz tylko zadbać o to, żeby 2 produkty w różnych tabelach nie miały takiego samego product_id (ale sprawdź najlepiej, z mysqlem mało miałem do czynienia). Tylko nie stosowałem nigdy takiego podejścia przy 2 tabelach linkujących do trzeciej, więc możesz jeszcze poszukać czy to ma sens.
Tak na przyszłość, jakbyś już miał trochę więcej czasu na testowanie, to w postgresie jest inheritance http://www.postgresql.org/docs/8.1/static/ddl-inherit.html
Może trochę źle to opisałem, dane wspólne to chodziło mi o wspólne kolumny, nie rekordy. Czyli np kazdy produkt ma np. kolumny wspólne nazwa, kolor, wysokość a kolumny specyficzne to np jedna grupa produktów ma np. szerokość i głębokość a jakaś inna grupa ma np. jasność, grubość, szybkość itp.
2 tabele będą napewno w jednej będą cechy wspólne produktu, w drugiej natomiast cechy specyficzne dla danej grupy produktów, tych grup cech specyficznych będzie 10 do max 20tu.
Czy lepiej dla każdej grupy produktów tworzyć osobną tabele czy raczej “upchnąć” to w jednej słownikowo jak w pierwszym poście. Metoda słownikowa wydaje się najbardziej elastyczna, gdy dochodzi nowa grupa nie trzeba dodawać tabeli, minusem jest że pole na wartość musi być zawsze varchar i czasem może ono przechowywać tylko 1 znak, więc spora nadmiarowość tu zachodzi.
[quote=Artur79]Może trochę źle to opisałem, dane wspólne to chodziło mi o wspólne kolumny, nie rekordy. Czyli np kazdy produkt ma np. kolumny wspólne nazwa, kolor, wysokość a kolumny specyficzne to np jedna grupa produktów ma np. szerokość i głębokość a jakaś inna grupa ma np. jasność, grubość, szybkość itp.
2 tabele będą napewno w jednej będą cechy wspólne produktu, w drugiej natomiast cechy specyficzne dla danej grupy produktów, tych grup cech specyficznych będzie 10 do max 20tu.
Czy lepiej dla każdej grupy produktów tworzyć osobną tabele czy raczej “upchnąć” to w jednej słownikowo jak w pierwszym poście. Metoda słownikowa wydaje się najbardziej elastyczna, gdy dochodzi nowa grupa nie trzeba dodawać tabeli, minusem jest że pole na wartość musi być zawsze varchar i czasem może ono przechowywać tylko 1 znak, więc spora nadmiarowość tu zachodzi.[/quote]
Ok, zupełnie nie zrozumiałem problemu w takim razie
Ciężkie pytanie, sam nie wiem co bym wybrał, ale nie wiem czy nie poszedł bym w stronę wielu tabel. I nawet nie chodzi o problem nadmiarowości, bo nie wiem czy to stworzy jakikolwiek problem, ale o to, że wszystko będziesz miał jako stringi i sam będziesz musiał dokonywać konwersji na inne typy. Nie jest to może przesadnie trudne, zakładając, że ten typ będziesz miał zapisany, ale ciężko jest przewidzieć w których momentach i przy jakich zapytaniach będzie Ci to przeszkadzać. Z drugiej strony dodawanie 20 tabel i później ich modyfikacja, to też jest pewien problem (dużo mniejszy oczywiście jezeli te tabele często się nie będą zmieniać, więc to też należy wziąć pod uwagę).
Sprawdzałeś może spree? Spree jest dość elastyczny, więc może coś ciekawego w tym temacie mają.
Zobacz jak rozwiązało to Spree (Products vs. Variants, Option Types + Option Values)
Skoro mają to dobrze rozwiązane to może lepiej: olej pisanie własnego sklepu i bierz spree
Ten aspekt spree jest akurat dosyć pokopany Przekombinowali moim zdaniem.
Ale zgadzam się: spree albo ror_commerce
Dzięki. To nie jest sklep, produkty to były tylko przykłady, więc nie mogę użyć gotowego sklepu, ale podpatrzeć coś tam można
Tych typów nie będzie aż tyle jak w standardowym sklepie.
Tak się przyglądam dyslusji i zastanawiam się - jeśli hstore mógłby znacznie uprościć implementację (nie miałem czasu się zagłębiać, ale z tego co ludzie tu pisali, mogłoby dać radę), to czy nie warto się zastanowić, czy zmiana bazy na dosyć mimo wszystko podobną nie zaoszczędzi tu więcej czasu niż dziwne rozwiązania na mysql. Nie chcę przesadnie przekonywać, ale racjonalnie by było rozważyć, co może pożreć więcej czas, tym bardziej jeśli projekt jest pilny. Polecam jednak rozpisać oba rozwiązania i spróbować to jakoś wyvenić - może da to obraz sytuacji. Obiecuję, że już więcej o psql ani słowa
Kwestia tego czy to rzeczywiście jest koniecznie i czy nie będzie dodatkowych utrudnien potem. Jak wygląda sprawa Sphinxa i tych pól hstore? Czy potrafi on je przeszukiwać ? Jak z validacjami ? Bo z tego co widzę zapytania konstruuje się troche inaczej https://github.com/softa/activerecord-postgres-hstore . Idealnie by było gdyby każda taka para klucz->wartość była przez activerecord widziana jak zwykła kolumna, czyli że można na tym odpalić wyszukiwanie, validacje itd
Nie potrafi. To generalnie jest bardzo świeży ficzer. Ale faktycznie pozwala fajnie zdenormalizować w wybranych sytuacjach. Natomiast proponowałbym Tobie jak mieć wszystko jak najbardziej znormalizowane i ewentualnie sobie zrobić w “produkcie” zserializowanego hasha z cache’em atrybutów, jeśli już chcesz oszczędzić joinów.
Być może wygodnie będzie zrealizować ten pomysł wykorzystując ActiveRecord::Store, wprowadzony w Railsach 3.2?