Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: podział zapisu rekordów na miesiące
Forum PHP.pl > Forum > Bazy danych > MySQL
fiasko
Do bazy w jednej tabeli planuje zapis dość sporo rekordów , a konkretnie 300 tyś dziennie.

Mam wobec tego pytanie jak zaplanować zapis i odczyt danych ?

Chcę podzielić zapisy na miesiące i co miesiąc tworzyć nową tabelę. Ale może są już jakieś dirvery gotowe do takich rzeczy ?
Nie chcę wymyślać koła na nowo.

Generalnie dane muszą być cały czas dostępne w systemie jak cofnę się w historii. Oczywiście chodzi o statystyki. Robił z was ktoś coś podobnego ? Chętnie wysłucham wasze opinie na to jak podejść do tematu .


wookieb
Tabela bez indeksów (poza kluczem głównym), silnik INNODB (silnik tabeli oczywiście), co jakiś czas statystyki przeliczane z pewnego zasięgu czasowego do oddzielnej tabeli (już z indeksami). Rekordy pobierane 1 po 1. Przy większych rozwiązaniach nie mówimy o Mysql. Wtedy to Cassandra, HBASE. Dla szybszego zapisu możesz zastosować dyski SSD ALBO odpowiednią maciesz RAID.
fiasko
O serwer się nie martwię bo jest w macierzy .

Kolega mi powiedział, że stosowanie podziału na miesiące jest bez sensu i nie potrzebnie będę tworzyć nowe tabele z nazwą każdego miesiąca.

Czy jeśli jako dodatkowe indeksy zdefiniuję datę i inne pola po których przeszukuję to czy jest sens robić ten podział tabel na miesiące ?

wookieb
No nie z nazwą. Z pełnym datetime-em dla danego początku miesiąca. Po to są te tabele żeby nie liczyć wszystkiego bez sensu przy każdym wyświetleniu statystyk. Poza tym nawet nie byłbyś w stanie SZYBKO tego obliczyć.
Pilsener
Zależy do czego to ma służyć i jak być wykorzystywane, pod jakim obciążeniem ma działać etc. Kiedyś miałem podobny problem z bazą klientów ale okazało się, że 99% userów wybiera przynajmniej region, więc podzieliłem tabele na kilkanaście mniejszych a wybór regionu zrobiłem obligatoryjnie, działało pięknie. Słyszałem też o partycjonowaniu(?) tabeli, można również szukać w wielu tabelach, tworzyć tabele pomocnicze zawierające potrzebne przeliczenia, wprowadzić system, który automatycznie utworzy nową tabelę gdy ilość rekordów dojdzie do 10 milionów etc. Kiedyś trzeba było się martwić, gdy był milion rekordów, dziś myślę, że jak masz dobry serwer bazy to MySql 10 milionów rekordów powinien uciągnąć.

I jeśli jest potrzebny tylko miesiąc albo miesiąc-rok to nie robiłbym datetime'a, lecz integery albo year + tinyint, będzie szybciej.
trafas
A może...

Zrobić jedną tabelę zawierającą aktualne dane ( z aktualnego miesiąca ) "tabela_aktual".

Zrobić drugą tabelę o takiej samej srtukturze, do której będą wrzucane dane archiwalne ( z poprzednich miesięcy ) "tabela_arch".

Tabela archiwalna byłaby napełniana z początkiem miesiąca - wszystkie dane z poprzedniego miesiąca po dacie byłyby do niej wrzucane. takie operacje najlepiej kręcić w JOBIE nocnym żeby nie zarzynać serwera.

Tym sposobem w tabeli na której bedziesz często miał operacj zapisu / odczytu będzie stosunkowo mało rekordów.

Odnośnie statystyk można zrobić podobnie - oddzielna tabela ze statystykami odnoście danych z archiwalnej tabeli - "statystyki_arch". Również uaktualniana na początku miesiąca, po uzupełnieniu tabeli z wpisami archiwalnymi.

W interfejsie możesz zrobić podzial na aktualne statystyki ( aktualny miesiąc ) i/lub z archiwum.
Ewentualnie możesz łączyć aktualne statystyki ( kręcone na bieżąco przy wywołaniu statystyk ) + dane z tabeli "statystyki_arch".

Pozdrawiam.
fiasko
No więc zrobiłem tak przy zapisie generuję sobie takie zapytanie :

Kod
mysql_query("
    CREATE TABLE IF NOT EXISTS x_stat_".$tabela_nazwa." (
id BIGINT( 255 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
site_id INT(11) NOT NULL ,
key_id INT(11) NOT NULL ,
wejsc INT(11) NOT NULL ,
link_type INT(11) NOT NULL ,
link_url VARCHAR(1024) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
proxy_query VARCHAR(15) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
date DATE NOT NULL ,
time TIME NOT NULL ,
INDEX ( `site_id` , `key_id` , `date` )
) ENGINE = MYISAM ");



Potem wypełniam tabelę . Danymi .

Na min robię 1000 - 2000 zapisów rekordów.

Ale już przeciętny użytkownik może na raz odczytać tylko wybrane przez siebie 3 miesiące. Co daje max około 264 960 000 rekordów.
Tak więc zapytanie pójdzie tak jakby było ich tylko tyle. Nawet po 5 latach będzie działać tak samo.



Każdy miesiąc nazywa się inaczej i składam to tak:

Kod
$rok = strftime('%Y',time());
$mies = strftime('%b',time());
$tabela_nazwa =$rok."_".$mies;
$tabela_nazwa = "x_stat_".$tabela_nazwa;


Wygenerowałem sobie jakiś jeden mld rekordów w pętli przy użyciu CRON. W pojedynczej tabeli za każdym razem przeszukiwało całą tabelę i trwało to dość długo. Oczywiście gdy ustawiłem indeks po dacie to było niemal identycznie jak z moim swichtem. Teraz sobie przekierowuję zapytania do innych tabel w PHP.

Problem był w tym, że system miał trzymać w pamięci ostanie 5 lat i potem przesuwać dane do archiwizacji. Dane w z archiwum będą trafiały na inny serwer i nie będą wykorzystywane w bieżącym działaniu w aplikacji.

Dlatego zrobiłem to po swojemu mimo, iż teoretycznie tak nie powinno się robić.

Ps. może ktoś sprawdzić czy dobrze tworzę tabelę ? Chodzi mi o to czy dobrze zoptymalizowana ?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.