Oznameni - casove rady v PostgreSQL
Pavel Stehule
stehule na kix.fsv.cvut.cz
Úterý Září 23 11:08:40 CEST 2003
Zdravim
Resil jsem problematiku ulozeni delsich (nad 30 tisic) casovych rad.
S prvni variantou, kdy jsem radu ukladal do pole, jsem prilis neuspel.
Prijemne mne prekvapilo, ze jsem ulozil bez problemu pole o 90000 prvcich,
mene prijemna skutecnosti bylo, ze generovani tohoto pole trvalo cca 25 minut
(na 2x P160) v PostgreSQL 7.4.2.
Dalsi varianta (uspesnejsi) je zalozena na transformaci rad do
pole bytu - bytea. (vhodnejsi by bylo zrejme navrhnout vlastni datovy typ).
Podpora casovych rad je napsana v C a obsahuje ctyri funkce time_series_pack,
time_series_unpack, time_series_unpack3, join_packed_time_series. Kod,
Makefile a generujici sql skript je k dispozici na
http://stehule.fsv.cvut.cz/~stehule/ts/
Povoleny zapis casovych rad je
1.21, 1.18, +1.252, -1.23
1.23, 111.282, 92.23, 2929
Vsechny radky musi mit stejny pocet sloupcu. Nelze vynechat cislo a ani
cislo zapsat v jinem formatu (napr. exponencialnim) - parser je holt
primitivni. Cisla se ukladaji jako float4. K prevodu do bytea slouzi funkce
time_series_pack. Pro opetovne ziskani casove rady pak funkce
time_series_unpack a time_series_unpack3. time_series_unpack vraci jeden
vybrany sloupec, t_s_unpack3 tri vybrane sloupce.
testdb011=# select * FROM time_series_unpack(
testdb011(# time_series_pack(
testdb011(# '10.23, 10.21, 10.222'||chr(10)||
testdb011(# '1.1, 2.5,3.10 '||chr(10)||
testdb011(# '1.1, 1.2,1.5'),1);
row | f
-----+-------
1 | 10.23
2 | 1.1
3 | 1.1
(3 øádek)
Funkce join_packed_time_series spoji dve zabalene rady. Psal jsem ji spis do
rezervy, nevedel jsem jak se interprety vyrovnaji s dlouhymi retezci (nad
2MB). Nakonec jsem ji nemusel pouzit.
testdb011=# select * FROM time_series_unpack(
testdb011(# join_packed_time_series(
testdb011(# time_series_pack(
testdb011(# '10.23, 10.21,10.222'||chr(10)||
testdb011(# '1.1, 2.5,3.10 '||chr(10)||
testdb011(# '1.1, 1.2, 1.5'),
testdb011(# time_series_pack(
testdb011(# '10.21, 10.21, 10.21')),2);
row | f
-----+-------
1 | 10.21
2 | 2.5
3 | 1.2
4 | 10.21
(4 øádek)
time_series_unpack3 zabrazi tri rady (3D) - posledni tri parametry urcuji
ktere to budou.
select * FROM
time_series_unpack3(
join_packed_time_series(
time_series_pack(
'10.23, 10.21, 10.222'||chr(10)||
'1.1, 2.5,3.10 '||chr(10)||
'1.1, 1.2, 1.5'),
time_series_pack(
'10.21, 10.21, 10.21')),1,2,3);
row | f1 | f2 | f3
-----+-------+-------+--------
1 | 10.23 | 10.21 | 10.222
2 | 1.1 | 2.5 | 3.1
3 | 1.1 | 1.2 | 1.5
4 | 10.21 | 10.21 | 10.21
(4 øádek)
Ukladani tri rad o 90 tis prvcich trva cca 10 sec, jejich zpracovani napr.
testdb011=# select max(row), avg(f1), max(f2) from time_series_unpack3(
testdb011(# (select ts from testts where idx=276),1,2,3);
max | avg | max
-------+------------------+---------
90000 | 49.9903243374202 | 99.9993
Total runtime: 24649.41 msec
(1 øádka)
cca 25 sec (. Zkouseno na PostgreSQL 7.4.2 (Pro nizsi verze by to melo byt
prelozitelne a provozuschopne take). Pro poradek - svoluji k volnemu pouziti
kodu pro komercni i nekomercni pouziti. Uvitam jakekoliv pripominky, napady,
opravy, zkusenosti z provozu
Pavel Stehule
Další informace o konferenci Databases