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