Wie kann ich bei Mysql die Anzahl der Datensätze begrenzen?
Also ich möchte gerne für eine Messwertaufzeichnung gerne der Tabelle
sagen, dass sie maximal 1000 Einträge haben darf, wenn ein neuer mit
INSERT hinzugefügt wird, dann soll automatisch der älteste gelöscht
werden.
Hintergrund: Ringbuffer für Messwertaufzeichnung.
Geht das überhaupt?
Oder muss ich das in der Applikation selbst programieren?
Danke für eure Hilfe.
Gruß Markus.
Regelmässig sinngemäss
delete from mytable where logtime < current timestamp - 1 day
laufen lassen und gut ist (oder so ähnlich, weiss grad nicht wie das in
mysql heisst).
In der Luxusvariante machst du sowas via Trigger.
Vielleicht ist mysql dann nicht die richtige Wahl für dein Projekt.
schau dir z.B. mal RRDTOOL an, das ist für round-robin-databases, genau
dein Anwendungsfall.
Da hast du für kurz zurückliegende Zeiträume (1000 Messungen) eine hohe
Auflösung, kannst aber trotzdem noch den gesamten Zeitraum (5 Jahre)
überblicken.
Und passende Tools zum graphischen Darstellen gibts auch gleich dazu.
@Peter:
Mein Rechner ist: Atom-CPU, 32GB SSD Disk, keine bewegten Teile, soll
autark 10 Jahre ganz alleine laufen! Nix Rechnertausch, kein User,
völlig autark.
@Ernst:
Das geht nicht. Die Applikation ist schon fast fertig. Nur noch die
"Kleinigkeit" mit der Aufzeichnung.
@A.K., alle:
Da würden sich Trigger "AFTER INSERT" eignen. Ich hab die nur noch nie
benutzt. Kann mir bitte jemand posten, wie sowas aussehen könnte?
Vielen Dank
Wirst dir erst einmal überlegen müssen, wie man rauskriegt was der
älteste Eintrag ist. Denn ausser dir kennt niemand die Tabelle.
Wenn das nicht immer genau 1000 Einträge sein müssen und eine Timestamp
drin ist, du also nach Alter gehen kannst, wird das deutlich einfacher
(siehe oben). Auf exakt 1000 Einträge zu begrenzen ist glaube ich etwas
haariger. Mit sequentieller ID geht das, aber nur, wenn darin garantiert
keine Löcher auftreten, was je nach Arbeitsweise und
Transaktionsverfahren nicht so sicher ist.
ich kann nur etwas allgemeines zu Triggern sagen.
Das ganze sind SQL Befehle (Proceduren) die Ausgeführt werden wenn ein
Datensatz geändert/eingefügt/gelöscht wurden.
Du müsstest sinnvoller weise ein ID Spalte haben die bei jedem Einfügen
um 1 Hochgezählt wird ( autoident).
Der Tigger macht dann
delete from XXX where ID < ( select max(ID) from XXX )-1000
damit hast du immer 1000 Einträge in der db.
aber durch das löschen kann es passieren das das ganze einfügen von
Datensätzen etwas verzögert wird.
Peter schrieb:
> Du müsstest sinnvoller weise ein ID Spalte haben die bei jedem Einfügen> um 1 Hochgezählt wird ( autoident).
Yep. Ausser wenn er irgendwann auf die Idee kommt, die Tabelle manuell
zu reparieren und mal mittendrin einen Eintrag löscht. Dann sind es eine
Weile lang nur noch 999. Auch bei Verwendung von Transaktionen kannst du
nicht unbedingt darauf setzen, dass keine Löcher entstehen.
Aber bei der hier anzunehmenden einfachsten Verwendung ist das wohl kein
Problem.
Aber wenn das konstant in regelmässigen Intervallen reinkommt, ist Zeit
ohnehin einfacher.
Ja, das ist die Tabelle:
[c]CREATE TABLE `tracker`.`aufz_1` (
`Datum` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
`Wert` DOUBLE NOT NULL
) ENGINE = InnoDB;
ALTER TABLE `aufz_1` ADD INDEX ( `Datum` ) ;
ALTER TABLE `aufz_1` ADD INDEX ( `Wert` );
[c]
Bau dir eine where clause, die auf der Basis von "Datum" alle veralteten
Einträge liefert. Das funktioniert in jeden SQL ein bischen anders, so
dass ich mysql grad nicht parat habe, geht da aber garantiert auch.
Entweder indem mit der aktuellen Zeit abzüglich irgendwas verglichen
wird, oder wenn die Differenz zur aktuellen Zeit zu gross wird.
Und wenn du das hast, dann ist der Schritt zu
create trigger ... after insert delete from ... where ...
nicht mehr weit.
Ich würde das asynchron machen.
Was spricht dagegen ein SQLSkript per Scheduler z.B ein mal am Tag aus
zu führen.
Das kuckt einfach auf geeignete Weise nach welche Sätze verworfen werden
können und gut ist.
wass willst du dennn immer mit dem Limit das ist hier fehl am platz.
SELECT Datum INTO dt FROM aufz_1 ORDER BY Datum DESC LIMIT 2,1;
du willst damit ja den ältesten datensatz löschen, richtig?
dann mach
delete from aufz_1 where Datum = ( select min(Datum) from aufz_1 );
Aber damit hast du nicht sichergestellt das dann immer 1000 Datensätze
drin sind, die löschst halt immer einen wenn einer eingefügt wird.
Was ist an dem Code falsch, warum geht das nicht?
Muss die Tabelle von einem bestimmten Typ sein? MyISAM, InnoDB, usw.?
(Jetzt hab ich auch kein LIMIT mehr drin)
Irgend was stimmt in der Zeile 2 nicht. Ich hab den Script nun so
geändert:
1
CREATETRIGGER`aufz_1_trg`AFTERINSERTON`aufz_1`
2
FOREACHROWBEGIN
3
DECLAREiINTDEFAULT0;
4
DECLAREdtTIMESTAMP;
5
SELECTCOUNT(Datum)INTOiFROMaufz_1;
6
WHILEi>3DO
7
SELECTMIN(Datum)INTOdtFROMaufz_1;
8
DELETEFROMaufz_1WHEREDatum=dt;
9
SETi=i-1;
10
ENDWHILE;
11
END
12
//
Jetzt füge ich mit INSERT Datensätz hinzu, und sobald ich den 5.
Datensatz hinzufügen möchte kommt diese Fehlermeldung:
#1442 - Can't update table 'aufz_1' in stored function/trigger because
it is already used by statement which invoked this stored
function/trigger.
Hmmm ... ???
scheint eine begrenzung in mysql zu sein, das man ein Tabelle im Tigger
nicht ändern kann.
Ich würde, wie oben schon erwähnt, einfach nachts ein job laufen lassen
der alle Datensätze älter als 24Stunden löscht. Ob nun 1000 oder 5000 in
der DB sind ist ja egal.
Ich wollte es halt "Perfekt" haben, egal von was für einem Client die DB
bedient wird...
... Und ich hab grad ein paar Minuten Zeit mich fortzubilden.
Möglichst viel die Datenbank automatisch machen lassen.
Dann nimm eine "richtige" Datenbank. Da du eh unter windows arbeitest
kannst du ja auch den SQL-Server von MS nehmen.
Der kann automatisiert jobs in der DB ausführen und das mit dem Tigger
geht dann auch.
MYSQL ist zwar schön, aber kommt noch nicht an die grossen DBs ran.
(die Expressversion von MS-SQL2008 ist kostenlos!)
naja Interbase ist heute wirklich veraltet - es läuft nicht sauber wenn
mehr als 1CPU vorhanden ist.
Es wird ja unter den Namen Firebird weiter entwickelt, aber so richt
schön finde ich sie auch nicht. Ab ein paar 100Mbyte datenbank größe
lässt die Performance recht stark nach. (oder ich weiss nicht wie man
das ding optimieren kann)
Ja, seit dem ich MySQL mit Lazarus und native Komponenten verwende ist
ein anderes Programm 10x schneller. Interbase >> tschüss. Damals, vor
vielen Jahren war die Anbindung von Interbase an Delphi um Welten
besser, erst jetzt ist mit "ZeosDBO" die Verwendung von MySQL super
einfach geworden.
Die ADO Komponenten sind einfach Schrott und viel langsamer.