mikrocontroller.net

Forum: PC-Programmierung MySQL, Datensätze begrenzen?


Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
soweit ich weiss geht es nicht. Da musst du dich schon selber drum 
kümmern.

Aber eine DB ist dazu da Daten zu speichern - also warum der Geiz?

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
300 Messwerte * 1440 Minuten/Tag  365 Tage  5 Jahre = 788400000 
Datensätze

Das schafft mein PC nicht !!!!

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn jeder datensatz 100Byte gross ist sind das auch bloss 80GB. Das 
schafft heute schon jeder REchner in 5Jahren erst recht.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Yep, rrdtool ist dafür besser geeignet.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mir hier ein Befehl zusammengebaggert, klappt aber nicht.
DELETE FROM aufz_1 ORDER BY Datum LIMIT SELECT (COUNT(Datum) - 3) AS X FROM aufz_1

Damit würden die letzten 3 Datensätze erhalten bleiben.
Aber irgendwie kann der das LIMIT nicht aus der SELECT Anweisung holen.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohne die Tabellenstruktur (und ggf. die mysql Version) zu kennen kann 
dir niemand wirklich konkret helfen, sondern nur Allgemeines absondern.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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]

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MySQL: das aktuelle XAMPP Paket V5.1

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Dieter Engelhardt (netdieter) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mal das versucht, aber ich kann nicht sagen ob es tut.
mein Apache/phpMyAdmin ist abgeschmiert (50% Rechenlast)
DELIMITER |

CREATE TRIGGER aufz_1_trg BEFORE INSERT ON aufz_1
BEGIN
  DECLARE dt TIMESTAMP;
  SELECT Datum INTO dt FROM aufz_1 ORDER BY Datum DESC LIMIT 2,1;
  DELETE FROM aufz_1 WHERE Datum < dt;
END;
|

DELIMITER ;
Könnte das gehen?

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab noch was anderes gemacht, also eine Kombination aus dem was oben 
gezeigt wurde:
DELIMITER |

CREATE TRIGGER aufz_1_trg BEFORE INSERT ON aufz_1
BEGIN
  DECLARE i INT DEFAULT 0;
  SELECT COUNT(Datum) INTO i FROM aufz_1;
  WHILE i > 3 DO
    DELETE FROM aufz_1 WHERE Datum = (SELECT MIN(Datum) FROM aufz_1);
    SET i = i - 1;
  END WHILE; 
END;|

DELIMITER ;

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)

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was kommt denn für eine Fehlermeldung?

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Irgend was stimmt in der Zeile 2 nicht. Ich hab den Script nun so 
geändert:
CREATE TRIGGER `aufz_1_trg` AFTER INSERT ON `aufz_1`
 FOR EACH ROW BEGIN
  DECLARE i INT DEFAULT 0;
  DECLARE dt TIMESTAMP;
  SELECT COUNT(Datum) INTO i FROM aufz_1;
  WHILE i > 3 DO
    SELECT MIN(Datum) INTO dt FROM aufz_1;
    DELETE FROM aufz_1 WHERE Datum = dt;
    SET i = i - 1;
  END WHILE; 
END
//

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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!)

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Früher hatte ich Interbsae benutzt, da hat sowas auch geklappt.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meinte Interbase von Borland

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.