ugrás a tartalomhoz

Több időzónás időpontok tárolása adatbázisban, statisztika és teljesítmény

fchris82 · 2012. Dec. 17. (H), 18.36
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?
 
1

időzóna

Poetro · 2012. Dec. 17. (H), 19.22
Azt fontos lehet hozzátenni, hogy az alkalmazás más időzónában futhat, mint a MySQL szerver, ami okozhat problémákat nem megfelelő beállítás esetén. A FROM_UNIXTIME függvény használatával egy INT egyszerűen emberi fogyasztásra alkalmassá tehető.
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

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.
2

Nem teljesen jogos

fchris82 · 2012. Dec. 17. (H), 20.06
Azt fontos lehet hozzátenni, hogy az alkalmazás más időzónában futhat, mint a MySQL szerver, ami okozhat problémákat nem megfelelő beállítás esetén.

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.

A FROM_UNIXTIME függvény használatával egy INT egyszerűen emberi fogyasztásra alkalmassá tehető.

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.

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.

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.
3

MySQL

janoszen · 2012. Dec. 17. (H), 22.14
MySQL-ben valo idotarolasrol itt irtam le mindent, amit tudni erdemes. Egyebkent hacsak nem szeretned pontosan a ket idopont kozott eltelt masodperceket kapni, idot nem hasznalunk intkent, egy nap ugyanis neha 86400 masodperc, neha 86401. Ebbol volt is borulas eleg csunyan a kozelmultban.
4

Hiba a hibában (tehát jó)

fchris82 · 2012. Dec. 17. (H), 23.24
Először is köszönöm a cikket, elolvastam :)
echo(
    date(
        "Y-m-d H:i:s",
        mktime(14, 0, 0, 3, 23, 2012)+86400*3
    )
);
Hoppá! Azt köpte ki, hogy 2012-03-26 15:00:00, tehát hiba van a gépezetben! Mi történt? 2012. március 24-én hajnalban Magyarországon váltottunk téli és nyári időszámítás között, azonban a kódunk órára pontosan 3 napot, tehát 72 órát adott hozzá az időponthoz.

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:
Egyebkent hacsak nem szeretned pontosan a ket idopont kozott eltelt masodperceket kapni

Sorry. Ugyanarról beszélünk.