Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Kilka mniejszych tabel, czy jedna duuuża, pomysł na zwiększenie wydajności mySQL... ale czy dobry ???
modic
post 25.02.2010, 02:30:09
Post #1





Grupa: Zarejestrowani
Postów: 64
Pomógł: 0
Dołączył: 18.07.2008

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


Sprawa wygląda tak, piszę dzienniczek ucznia i jest tam tabela z ocenami (każda ocena oddzielny rekord), przewiduję że może osiągnąć ponad 100 000 000 rekordów.

Przy testowaniu wydajności z ok 1.5 mln ocen, przy pobieraniu oceny ucznia, albo oceny z przedmiotu w danej klasie, zapytania wykonywały się w ok 0.6 sec, często krócej, (0.1 przy 30 tyś ocen) na tabelę są założone 4 indeksy, po ich usunięciu pokazanie ocen jednego ucznia trwało ponad 60 sec :/
Usuwanie, albo edycja pojedynczych rekordów trwa jednak zdecydowanie za długo, raz 0.2 a raz nawet 2 sec.
Ale z drugiej strony ta tabela może być często aktualizowana.

Tak więc zastanawiam się czy nie dobrym wyjściem było by zamiast jednej dużej tabeli OCENY dla wszystkich szkół w systemie, zrobić automatycznie dla każdej szkoły oddzielną tabelę na oceny, np OCENY_SZKOLA01, OCENY_SZKOLA02
Liczba szkół nie powinna przekroczyć 200, a w jednej tabeli byłby max 1mln rekordów.

Serwer to nie dedyk, jakiś współdzielony, nie znam jego parametrów.

Tak wiec pytam, jak oceniacie ten pomysł, dobry, zły i czy mogą być jakieś negatywne konsekwencje, a może macie inny pomysł na poprawę wydajności, oczywiście poza budowaniem własnego data center questionmark.gif?
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 10)
Mchl
post 25.02.2010, 09:40:51
Post #2





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

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


Pomysł zły.
Lepiej partycjonować.

Jakiego typu tabela?

Nie mówiąc o tym, że na współdzielonym serwerze to może masz 128MB RAM, a może nie, więc masz ciągle odczyty i zapisy na dysku.
Go to the top of the page
+Quote Post
modic
post 25.02.2010, 10:32:06
Post #3





Grupa: Zarejestrowani
Postów: 64
Pomógł: 0
Dołączył: 18.07.2008

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


Serwer to maszyna współdzielona, ale stoi na nim kilka dużych serwisów, więc raczej ma więcej niź 126MB ram smile.gif

Typ tabel to InnoDB

Wersja serwera: 5.0.84-v2+tld1-log

Partycjonowanie było by dobre, nawet nie wiedziałem że jest coś takiego, ale chyba byłaby konieczna aktualizacja mysql
Go to the top of the page
+Quote Post
Mchl
post 25.02.2010, 11:02:56
Post #4





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

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


Cytat(modic @ 25.02.2010, 10:32:06 ) *
Serwer to maszyna współdzielona, ale stoi na nim kilka dużych serwisów, więc raczej ma więcej niź 126MB ram smile.gif


Chodzi o to ile jest dostępne dla Ciebie. A jeżeli wszystkie te duże serwisy stoją na jednym serwerze mysql, to nie dziw się, że Twoje rzadziej używane tabele są zrucane na dysk, kosztem częściej używanych tabel z tamtych serwisów.

Ten post edytował Mchl 25.02.2010, 11:03:17
Go to the top of the page
+Quote Post
Pilsener
post 4.03.2010, 21:46:37
Post #5





Grupa: Zarejestrowani
Postów: 1 590
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

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


Cytat
100 000 000 rekordów
- zapomnij. Właściwą wydajność zapewnisz tylko poprzez partycjonowanie danych i ich rozdzielenie na kilka serwerów, pomyśl o tym, ile mkw zajmuje serwerownia np. dużego banku czy choćby jakaś baza danych linii lotniczych. Najlepiej od razu pomyśl o miejscu w jakimś data center i swoich serwerach, wyjdzie taniej.

I w ogóle nie wiem, czy mysql jest odpowiedni do tak dużej liczby danych...
Go to the top of the page
+Quote Post
Mchl
post 4.03.2010, 22:38:12
Post #6





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

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


Sama ilość rekordów o niczym nie mówi. Liczy się objętość. Do 500GB MySQL sobie radzi na jednym serwerze całkiem dobrze (ale nie na współdzoelonym!).
Go to the top of the page
+Quote Post
modic
post 12.03.2010, 21:37:45
Post #7





Grupa: Zarejestrowani
Postów: 64
Pomógł: 0
Dołączył: 18.07.2008

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


Dzięki za podpowiedzi

sam serwer to dedyk, ale do dyspozycji jest tylko połowa mocy obliczeniowej, w każdym razie do 5 mln ocen jeszcze sobie radzi, ale przy większym ruchu mogą być problemy, a o wydajności wato pomyśleć wcześniej niż gdy jest troszkę za późno, choć zanim się uzbiera te 5 mln ocen to się troszkę zejdzie, jeden uczeń to ok 200 ocen przez rok

tabela oceny z 5 mln rekordów to ok 600mb, są


A skoro już jesteśmy przy temacie partycjonowania, w którym jestem jak narazie zielony, to czy takie oznaczenie klucza głównego będzie prawidłowy, ew. czy nie będzie z nim problemów:
  1. PRIMARY KEY (`oceny_id`,`oceny_szkola`,`oceny_year`,`oceny_semestr`,`oceny_przedmiot`,`oceny_uczen`,`oceny_kolumna`,`oceny_ocena`,`oceny_ocena_pm`)

bo mysql wyrzuca mi błąd: "A PRIMARY KEY must include all columns in the table's partitioning function"

w efekcie mam takie coś:
  1. CREATE TABLE IF NOT EXISTS `oceny` (
  2. `oceny_id` int(11) NOT NULL AUTO_INCREMENT,
  3. `oceny_szkola` int(11) NOT NULL DEFAULT '0',
  4. `oceny_year` int(11) NOT NULL DEFAULT '0',
  5. `oceny_semestr` int(11) NOT NULL DEFAULT '0',
  6. `oceny_przedmiot` int(11) NOT NULL DEFAULT '0',
  7. `oceny_uczen` int(11) NOT NULL DEFAULT '0',
  8. `oceny_kolumna` int(2) NOT NULL DEFAULT '0',
  9. `oceny_ocena` int(1) NOT NULL DEFAULT '0',
  10. `oceny_ocena_pm` varchar(2) NOT NULL,
  11. PRIMARY KEY (`oceny_id`,`oceny_szkola`,`oceny_year`,`oceny_semestr`,`oceny_przedmiot`,`oceny_uczen`,`oceny_kolumna`,`oceny_ocena`,`oceny_ocena_pm`),
  12. KEY `oceny_year` (`oceny_year`),
  13. KEY `oceny_przedmiot` (`oceny_przedmiot`),
  14. KEY `oceny_uczen` (`oceny_uczen`)
  15. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
  16.  
  17. PARTITION BY LIST (oceny_szkola)
  18. (
  19. PARTITION s1 VALUES IN (1) ENGINE = InnoDB,
  20. PARTITION s2 VALUES IN (2) ENGINE = InnoDB,
  21. PARTITION s3 VALUES IN (3) ENGINE = InnoDB
  22. );

cel był taki żeby każda szkoła miała oddzielną partycję i oceny były pobierane tylko z jednej partycji
Go to the top of the page
+Quote Post
Mchl
post 12.03.2010, 21:58:42
Post #8





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

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


Do duszy taki klucz główny.
Przeczytaj definicję klucza głównego i sprawdź czy to co wymyśliłeś ją spełnia.

Wskazówka: Klucz ma zawierać wszystkie kolumny identyfikujące partycje, a nie wszystkie kolumny tabeli biggrin.gif

P.S. Jedna szkoła na partycję to może być lekki overkill.

Ten post edytował Mchl 12.03.2010, 22:07:15
Go to the top of the page
+Quote Post
modic
post 12.03.2010, 22:44:20
Post #9





Grupa: Zarejestrowani
Postów: 64
Pomógł: 0
Dołączył: 18.07.2008

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


hehe

Też bym wolał np PRIMARY KEY (`oceny_id`), ale mam mały problem i nie wiem jak go obejść

Gdy podzielę tabelę na partycję wg kolumny 'oceny_szkola' to AUTO_INCREMENT mogę dodać tylko do kolumny 'oceny_szkola', inaczej wywala błąd, ew zrobić PRIMARY KEY tak jak zrobiłem, czyli w dupny sposób.
Efekt jest taki że rekordy w tabeli 'oceny_id' są puste i nie można edytować, ani usuwać ocen, bo nie mogę do niej zastosować AUTO_INCREMENT sad.gif

Oczywiście problem by znikł gdyby partycje były np typu RANGE i były tworzone wg 'oceny_id', ale w skrajnym przypadku przeszukiwane mogłyby być nawet wszystkie partycje, a raczej byłoby lepiej gdyby przeszukiwana była tylko jedna (tak mi się wydaje, mogę się mylić).

Chyba jednak zrobię ten range...

P.S.
niekoniecznie overkill, 1000 uczniów w 5 lat jest w stanie uzbierać 1 mln ocen, czyli sporo
Go to the top of the page
+Quote Post
Mchl
post 13.03.2010, 09:30:19
Post #10





Grupa: Zarejestrowani
Postów: 855
Pomógł: 145
Dołączył: 17.07.2008
Skąd: High Memory Area

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


PRIMARY KEY (`oceny_id`,`oceny_szkola`) próbowałeś?
Co to jest milion ocen... I to jeszcze w takich krótkich rzędach.

PS. Zamiast
Kod
  `oceny_year` int(11) NOT NULL DEFAULT '0',

lepiej
Kod
  `oceny_year` year NOT NULL DEFAULT '0',


PPS. Chyba, że to rok szkolny... nie pomyślałem... ale nawet wtedy TINYINT raczej wystarczy. Podobnie jak w innych kolumnach, zamist INT możesz dać mniejsze typy. Jeden, dwa bajty, przemnożone przez te miliony ocen, dadzą Ci konkretne oszczędności.

Ten post edytował Mchl 13.03.2010, 09:34:12
Go to the top of the page
+Quote Post
modic
post 13.03.2010, 14:07:06
Post #11





Grupa: Zarejestrowani
Postów: 64
Pomógł: 0
Dołączył: 18.07.2008

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


faktycznie, PRIMARY KEY (`oceny_id`,`oceny_szkola`) zadziałało, wielkie dzięki za pomoc smile.gif
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: 13.08.2025 - 22:41