Frage zur Speicherung von Datenbanken

hans32

Benutzer
Beiträge
14
Hallo zusammen,

ich habe mal eine Frage zur theoretischen Behandlung der Daten in einer Datenbank. Wenn ich Daten logge, die über einen längeren Zeitraum den gleichen Wert haben (zum Beispiel minütlich gemessen über eine Stunde) speichert die DB dann 60 Werte ab oder wird das optimiert gemacht? Im Prinzip würde es ja reichen den Start und Endzeitpunkt zu speichern.... Lohnt es sich da irgendwie zu optimieren?
 
Werbung:

akretschmer

Datenbank-Guru
Beiträge
9.028
Hallo zusammen,

ich habe mal eine Frage zur theoretischen Behandlung der Daten in einer Datenbank. Wenn ich Daten logge, die über einen längeren Zeitraum den gleichen Wert haben (zum Beispiel minütlich gemessen über eine Stunde) speichert die DB dann 60 Werte ab oder wird das optimiert gemacht? Im Prinzip würde es ja reichen den Start und Endzeitpunkt zu speichern.... Lohnt es sich da irgendwie zu optimieren?

Es gibt sicher Datenbanken, die das optimieren können. Du könntest ja auch ein komprimierendes Filesystem verwenden. Aber ich würde erst einmal davon ausgehen, daß es NICHT optimiert gespeichert wird.

Wenn Du das also statt minütlich dann doch eher mit von-bis und den Wert speichern willst würde ich selber dafür sorgen, daß es so ist. Zum Beispiel via TRIGGER, das dürfte eher trivial sein (für Dein Beispiel).

Bedenke auch, daß Du das dann anders abfragen müßtest. In PG würde ich z.B. zu TSRANGE greifen - also ein timestamp-range als Datentyp für den Zeitpunkt.
 

gurbelunder

Datenbank-Guru
Beiträge
136
Das hängt ganz schwer von diesen hauptsächlichen Faktoren ab:

- Was für eine Datenbank und in welcher Version?
- Wie wird geloggt?

Grundsätzlich ist ein Logging "dumm". Es prüft dann, wenn es prüfen soll und schreibt sich den Wert nieder. Hierbei wird nicht beachtet, ob der Wert schon vorhanden ist oder nicht. Das müsste man dem Loggingdann dementsprechend beibringen bzw. einstellen.
 

akretschmer

Datenbank-Guru
Beiträge
9.028
Grundsätzlich ist ein Logging "dumm". Es prüft dann, wenn es prüfen soll und schreibt sich den Wert nieder. Hierbei wird nicht beachtet, ob der Wert schon vorhanden ist oder nicht. Das müsste man dem Loggingdann dementsprechend beibringen bzw. einstellen.

ACK.

Manche Datenbanken können selber komprimieren, für meine Lieblings-DB ist das z.B. hier beschrieben: http://www.postgresql.org/docs/9.3/static/storage-toast.html Aber das greift in dem genannten Fall nicht, das ist eher was für große Texte oder so.
 

hans32

Benutzer
Beiträge
14
OK, danke für eure Antworten! Also ist es notwendig selber für die optimierte Speicherung zu sorgen, es reicht nicht, einfach die Daten abzulegen und die DB versteht von selber, dass es hier nur gleiche Werte zu speichern gibt...
 

gurbelunder

Datenbank-Guru
Beiträge
136
OK, danke für eure Antworten! Also ist es notwendig selber für die optimierte Speicherung zu sorgen, es reicht nicht, einfach die Daten abzulegen und die DB versteht von selber, dass es hier nur gleiche Werte zu speichern gibt...

Vom Ansatz her wirst du sicher nicht drum herum kommen, dir dort selber etwas auszudenken. Vor allem mach sich das sehr praktisch, wenn man ein solches loggen nur für bestimmte Tabellen oder der gleichen haben möchte.

Einfach mal ein kleines Beispiel von mir:
Mittels diesem SQL Snippet prüfe ich eine view namens "" in Oracle nach durchgelaufenen Backupjobs:

(der Teil am Anfang sind einfach Formatierungsgeschichten)

Code:
SET LINESIZE 210
SET PAGESIZE 60
SET COLSEP |

COL ADDITIONAL_INFO FORMAT A100
COL STATUS FORMAT A9
COL LOG_DATE FORMAT A34
COL JOB_NAME FORMAT A24
COL LOG_ID FORMAT 999,999
COL ERROR# FORMAT 999

SELECT LOG_ID, LOG_DATE, JOB_NAME, STATUS, error#, additional_info FROM dba_scheduler_job_run_details WHERE job_name LIKE '%BACKUP%' ORDER BY 2 DESC;
 

akretschmer

Datenbank-Guru
Beiträge
9.028
OK, danke für eure Antworten! Also ist es notwendig selber für die optimierte Speicherung zu sorgen, es reicht nicht, einfach die Daten abzulegen und die DB versteht von selber, dass es hier nur gleiche Werte zu speichern gibt...

Genau. Um es mal für meine Lieblings-DB zu zeigen:

Code:
test=*> select * from log;
id |  ts  | value
----+---------------------+-------
  1 | 2013-10-29 11:00:01 |  10
  2 | 2013-10-29 11:00:02 |  20
  3 | 2013-10-29 11:00:03 |  20
  4 | 2013-10-29 11:00:04 |  20
  5 | 2013-10-29 11:00:05 |  20
  6 | 2013-10-29 11:00:06 |  20
  7 | 2013-10-29 11:00:07 |  30
  8 | 2013-10-29 11:00:08 |  30
  9 | 2013-10-29 11:00:09 |  30
(9 rows)

test=*> select distinct min(ts) over (partition by x) as von, max(ts) over (partition by x) as bis, value from (select *, sum(wechsel) over (order by ts) as x from (select *, case when lag(value) over (order by ts) != value then 1 else 0 end as wechsel from log) foo) bar;
  von  |  bis  | value
---------------------+---------------------+-------
2013-10-29 11:00:01 | 2013-10-29 11:00:01 |  10
2013-10-29 11:00:02 | 2013-10-29 11:00:06 |  20
2013-10-29 11:00:07 | 2013-10-29 11:00:09 |  30
(3 rows)

Könnte man noch erweitern, z.B. statt von und bis gleich TSRANGE - Typen verwenden & Index drauf.

Also so:

Code:
test=*> select distinct ('[' || (min(ts) over (partition by x))::text || ',' || (max(ts) over (partition by x))::text || ']')::tsrange, value from (select *, sum(wechsel) over (order by ts) as x from (select *, case when lag(value) over (order by ts) != value then 1 else 0 end as wechsel from log) foo) bar;
                    tsrange                    | value
-----------------------------------------------+-------
["2013-10-29 11:00:07","2013-10-29 11:00:09"] |    30
["2013-10-29 11:00:02","2013-10-29 11:00:06"] |    20
["2013-10-29 11:00:01","2013-10-29 11:00:01"] |    10
(3 rows)

Das in einer Tabelle speichern (z.B. einmal am Tag via Cron), dann kann man da auch schön suchen:

Code:
test=*> create table new_log as select distinct ('[' || (min(ts) over (partition by x))::text || ',' || (max(ts) over (partition by x))::text || ']')::tsrange zeitraum, value from (select *, sum(wechsel) over (order by ts) as x from (select *, case when lag(value) over (order by ts) != value then 1 else 0 end as wechsel from log) foo) bar;
SELECT 3
test=*> select * from new_log where zeitraum @> '2013-10-29 11:00:04'::timestamp;
                  zeitraum                    | value
-----------------------------------------------+-------
["2013-10-29 11:00:02","2013-10-29 11:00:06"] |    20
(1 row)
 
Zuletzt bearbeitet:
Werbung:

ukulele

Datenbank-Guru
Beiträge
4.394
Grundsätzlich ist ein Logging jede Minute um Veränderungen in einer Tabelle zu dokumentieren ziemlich sinnfrei. Da würde ich in jedem Fall zu einem Trigger raten der nur Veränderungen und genau dann loggt, wenn sie passieren.
 
Oben