Több időzónás időpontok tárolása adatbázisban, statisztika és teljesítmény
Egy időmérő programot kellene csinálni, tehát mérni kellene, hogy ki, mettől-meddig és mit csinált, ebből pedig aztán statisztikákat készíteni, mindezt különböző időzónákban. Felmerült kérdések:
MySQL-ben DATETIME vs TIMESTAMP vs INT vs kombinálás?
Van itt egy cikk: http://gpshumano.blogs.dri.pt/2009/07/06/mysql-datetime-vs-timestamp-vs-int-performance-and-benchmarking-with-myisam/ Következtetéseim:
DATETIME: Gyorsabb, mint a TIMESTAMP, emberileg olvasható kódot eredményez, statisztika készítéshez használhatóak a MySQL beépített dátumkezelő függvényei, ellentétben az INT-tel. Tehát anélkül, hogy matemateikailag kellene kiszámolgatni és új értékeket képezni, lehet "group by"-olni napokra: GROUP BY DAY(datum). Nehézkes viszont összeszámolni, hogy egy-egy feladattal mennyi idő ment el (lásd INT). Továbbá csak program oldalon lehet az időzónát kezelni, mindenképpen ott konvertálni kell, ez megint csak megnehezíti, amikor össze kell számolni, hogy adott napon mennyit dolgozott az illető.
TIMESTAMP: Ez is olvasható kódot eredményez, használhatóak rá a dátum fv-ek. A különbség a DATETIME-hoz képest, hogy egyrészt lassabb a cikk szerint, ugyanakkor automatikusan lekezeli az időzónákat (és kevesebb helyet foglal, de ez most nem tűnik relevánsnak). SET time_zone = ... -nal minden kapcsolatnál be lehet állítani és akkor mindenféle macera nélkül lehet GROUP BY-olni megint csak. Hátrány még, hogy a Doctrine nem támogatja alapból ezt az oszlop típust.
INT: Ha nem bízzuk a MySQL-re lekérdezésben az időbélyeg számítást, akkor a leggyorsabb. Viszont nem használhatóak a beépített dátum függvények, nekem kell a lekérdezésekben matematikai műveletekkel, osztásokkal és kerekítésekkel kiszámolni, hogy egy adott időbélyeg melyik napnak felel meg. Egyáltalán nem olvasható a kód emberileg, a lekérdezések mindenképpen bonyolultabbak, ez a megoldás még kevésbé kompatibilis a Doctrine-nal talán, mint a TIMESTAMP . VISZONT! Itt nagyon gyorsan meg lehet kapni, hogy egy-egy feladattal mennyi idő ment el, SUM-mázni kell a kezdő és a vég időbélyegeket, majd a két számot ki kell vonni egymásból.
KOMBINÁLÁS: Lenne a DATETIME vagy TIMESTAMP és azt kombinálnám egy trigger segítségével; lenne 3-6 plusz oszlop, ami a statisztika készítés miatt minden INSERT vagy UPDATE esetén frissülne. Tehát előre kiszámolnám mindig, hogy egy dátumnak mi a UNIX időbélyege, az hanyadik óra és hanyadik nap, esetleg még hanyadik hét, hanyadik hónap, hanyadik év az adott időzóna szerint, így a MySQL lekérdezésben már egyszerű, indexelt számok alapján kellene GROUP BY-olni. Megmarad az olvasható kód is és gyors is elméletileg. Persze mindjárt okosabb lennék, ha lehetne tudni, mennyi lesz az INSERT/UPDATE - SELECT arány, mert lehet, hogy a trigger nagyobb problémát okoz, mint amennyit megold, bár elméleti szinten, valószínűleg egy adat többször kerül majd lekérdezésre, mint írásra, ezért a konverziót jobb az írásnál elvégezni.
MySQL vs MongoDB vs más vs kombinálás?
Nem használtam még NoSQL-t, így ebben nem igazán van tapasztalatom és ismeretem, azonban felmerült bennem, hogy ebben az esetben lehet, hogy jobban megfelel a célnak egy MongoDB, mint a MySQL. Vki tapasztalattal rendelkező ebben cáfolna vagy megerősítene?
■ MySQL-ben DATETIME vs TIMESTAMP vs INT vs kombinálás?
Van itt egy cikk: http://gpshumano.blogs.dri.pt/2009/07/06/mysql-datetime-vs-timestamp-vs-int-performance-and-benchmarking-with-myisam/ Következtetéseim:
DATETIME: Gyorsabb, mint a TIMESTAMP, emberileg olvasható kódot eredményez, statisztika készítéshez használhatóak a MySQL beépített dátumkezelő függvényei, ellentétben az INT-tel. Tehát anélkül, hogy matemateikailag kellene kiszámolgatni és új értékeket képezni, lehet "group by"-olni napokra: GROUP BY DAY(datum). Nehézkes viszont összeszámolni, hogy egy-egy feladattal mennyi idő ment el (lásd INT). Továbbá csak program oldalon lehet az időzónát kezelni, mindenképpen ott konvertálni kell, ez megint csak megnehezíti, amikor össze kell számolni, hogy adott napon mennyit dolgozott az illető.
TIMESTAMP: Ez is olvasható kódot eredményez, használhatóak rá a dátum fv-ek. A különbség a DATETIME-hoz képest, hogy egyrészt lassabb a cikk szerint, ugyanakkor automatikusan lekezeli az időzónákat (és kevesebb helyet foglal, de ez most nem tűnik relevánsnak). SET time_zone = ... -nal minden kapcsolatnál be lehet állítani és akkor mindenféle macera nélkül lehet GROUP BY-olni megint csak. Hátrány még, hogy a Doctrine nem támogatja alapból ezt az oszlop típust.
INT: Ha nem bízzuk a MySQL-re lekérdezésben az időbélyeg számítást, akkor a leggyorsabb. Viszont nem használhatóak a beépített dátum függvények, nekem kell a lekérdezésekben matematikai műveletekkel, osztásokkal és kerekítésekkel kiszámolni, hogy egy adott időbélyeg melyik napnak felel meg. Egyáltalán nem olvasható a kód emberileg, a lekérdezések mindenképpen bonyolultabbak, ez a megoldás még kevésbé kompatibilis a Doctrine-nal talán, mint a TIMESTAMP . VISZONT! Itt nagyon gyorsan meg lehet kapni, hogy egy-egy feladattal mennyi idő ment el, SUM-mázni kell a kezdő és a vég időbélyegeket, majd a két számot ki kell vonni egymásból.
KOMBINÁLÁS: Lenne a DATETIME vagy TIMESTAMP és azt kombinálnám egy trigger segítségével; lenne 3-6 plusz oszlop, ami a statisztika készítés miatt minden INSERT vagy UPDATE esetén frissülne. Tehát előre kiszámolnám mindig, hogy egy dátumnak mi a UNIX időbélyege, az hanyadik óra és hanyadik nap, esetleg még hanyadik hét, hanyadik hónap, hanyadik év az adott időzóna szerint, így a MySQL lekérdezésben már egyszerű, indexelt számok alapján kellene GROUP BY-olni. Megmarad az olvasható kód is és gyors is elméletileg. Persze mindjárt okosabb lennék, ha lehetne tudni, mennyi lesz az INSERT/UPDATE - SELECT arány, mert lehet, hogy a trigger nagyobb problémát okoz, mint amennyit megold, bár elméleti szinten, valószínűleg egy adat többször kerül majd lekérdezésre, mint írásra, ezért a konverziót jobb az írásnál elvégezni.
MySQL vs MongoDB vs más vs kombinálás?
Nem használtam még NoSQL-t, így ebben nem igazán van tapasztalatom és ismeretem, azonban felmerült bennem, hogy ebben az esetben lehet, hogy jobban megfelel a célnak egy MongoDB, mint a MySQL. Vki tapasztalattal rendelkező ebben cáfolna vagy megerősítene?
időzóna
FROM_UNIXTIME
függvény használatával egyINT
egyszerűen emberi fogyasztásra alkalmassá tehető.Hát, ha időzónákkal dolgozol, akkor egyébként is neked kell számolnod egy csomó ilyet, mivel más időzónára kell konvertálni az adatokat, mint amiben vannak.
Nem teljesen jogos
Ez TIMESTAMP esetén nem okoz problémát, csak DATETIME-nál. Tegnap este egy Stackoverflow-s válaszban volt egy olyan mondat, amiben azt írták, pont ezért használ a FB is TIMESTAMP-et, mert így teljesen mindegy, hogy milyen szerverbeállításokkal fut az adott szerver. Persze azt nem tudom, hogy valóban így van-e. Viszont "cserébe" 30-50%-kal lassabb sebességgel fut az összehasonlítás és keresés. DATETIME esetén nyilván UTC szerint kerülne mentésre az adat és script oldalon kell konvertálni a megfelelőre, csak a statisztika készítést az nem kicsit bonyolítja. Kb akkor mondjuk PHP-ban kell összeadogatni az értékeket, hogy melyik nap mennyi munka is történt, BÁR, ez nem feltétlenül baj, mert az éjfél előtt kezdett munka, ami éjfél után ér véget, az még okozhat problémát, ha egyszerű SQL lekérdezéssel akarom megkapni a napi eredményeket.
Ez ugyan igaz, de egy gyors hibakeresést máris bonyodalmasabbá tesz, hogy nem használható pl a
select * from timelog order by created_at desc limit 20;
, hanem végig kellene mennem és konvertálnom kellene az összes dátumot, hogy lássam mi van.Erre vannak a php-ban és a mysql-ben is beépített fv-ek, tehát ez az időzónáról időzónára váltás nem feltétlenül akkora probléma, mint az, amikor statisztikákat kell gyártani a meglévő adatokból.
MySQL
Hiba a hibában (tehát jó)
Te hibának bélyegzel vmit, ami nem hiba. A példakódodban azt mondod a programnak, hogy "keressük azt az időpontot, ami 72 óra múlva van", mert mondjuk annyit kell aszalódnia a kovászos uborkának a napon. És itt most egy nagyon fontos dolog jön, amit figyelmen kívül hagysz az én esetemben és éppen hibás stratégiát javasolsz: Én itt időkülönbségeket akarok mérni! Egy kezdeti és egy vég dátum között eltelt idő fontos nekem. A DST miatt pont, hogy az időbélyegre van szükségem, ugyanis van nap, amikor kétszer van 02:30, ezért ha nem időbélyeget - integert - használok, akkor bizony még az is előfordulhat, hogy -15 perc munka jön ki eredményként, mert elkezdi a munkát 02:30-kor, megtörténik az óraátállás, majd háromnegyed óra múlva, 02:15-kor fejezi be, akkor bizony az adatbázisban a záró időpont látszólag kisebb, mint a kezdeti. Tehát az én szempontomból pont a "szöveges" dátumtárolás vezet rossz eredményhez. És bizony-bizony, ha vki 2012-03-26 15:00:00-kor fejezi be a munkát, akkor az 72 órát dolgozott, nem 73-t, amit a program helytelenül számolna a "te esetedben", ha balga módon kiszámolnám a nap és óra különbségeket (nem pedig az ehhez szükséges fv-kkel számolnám a különbséget)
Félre értés ne essék, jó, amit írsz, de az én esetemben az általad hibás működésnek vélt eset pont, hogy előny, míg a "helyes" út pont, hogy rossz.
Van már tapasztalatom, és ahogy te is írtad, a unix időbélyeg és a "szöveges" dátum konverzió között megfelelő fv-ek állnak rendelkezésre mind PHP, mind MySQL alatt is, azokat kell használni.
Köszönöm, hogy ezt így most végig gondolhattam, egyre inkább úgy tűnik, hogy az időbélyeg tárolás kell nekem, és el kell tárolni a hozzá tartozó dátum adatokat is, melyik napnak felelt az meg, melyik hétnek, hónapnak és évnek, mert a statisztika ez alapján kerül "group by"-olásra.
UPDATE
Ajjajaj, mire elolvastam a cikket, elfelejtettem, hogy mit írtál pontosan:
Sorry. Ugyanarról beszélünk.