Zum Inhalt springen

Empfohlene Beiträge

Geschrieben

Hallo zusammen,

ich sitze hier auf ner MySQL-DB die sich um die 100Mio Zeilen (aus Logdateien) bewegt. Mein Problem ist, dass ich eine Maske in PHP gebastelt habe mit der ich die Logeinträge filtern kann. Nur wie ihr euch vorstellen könnt, können diese Anfragen schon mal ein paar Minuten dauern.

Zu meiner Frage:

Ist es irgendwie möglich rein mit PHP und MySQL eine query abzubrechen? Denn der Standarduser wartet natürlich nicht gern und klickt nochmal und nochmal... was jedes mal wieder eine Query startet.

Ich würde gerne die ursprüngliche Query abbrechen, falls nochmal geklickt wird. Hab aber noch keinen Weg dazu entdeckt.

Ich weiß, dass man einen Prozess, mit Hilfe der ID killen kann, aber ein SHOW PROCESSLIST kann ich nicht absetzen bzw. wird gelocked bis der vorhergehende Query fertig ist.

Grüße

Dukanos

Geschrieben
Nur wie ihr euch vorstellen könnt, können diese Anfragen schon mal ein paar Minuten dauern.

Nein kann ich nicht. Du hast als Ergebnismenge ja wohl nicht zehntausende Sätze oder? Indizier die Tabelle vernünftig, dann ist das eine Sache von Sekunden(bruchteilen).

Dim

Geschrieben

Ich hab auf allem nach dem gesucht/gefiltert werden kann nen Index und die Ergebnismenge sind gerne mal über 10.000 Sätze...

Wie gesagt 100Mio aktuell und jeden Tag laufen im Moment weitere 300.000/Tag rein.

Achja, die Tabelle ist übrigends MyISAM... da ich u.A. auch Volltextsuche benötige.

Geschrieben

Ok. Dann halt ich eine reine Webanwendung dafür aber auch eher für ungeeignet, denn ein statuslose Protokoll ist für solche OLAP Auswertungen m.M. nach ungeeignet (Beispiel Browser schließen, einen neuen öffnen und neue Abfrage starten etc).

Ich würd das so implementieren, dass Du über die Weboberfläche einen Job antriggerst der dann in der DB läuft und dem User das Ergebnis zur Verfügung stellt (z.B. in dem eine Zwischentabelle befüllt wird o.Ä.).

Während der Laufzeit bekommt der User nur eine Statusmeldung angezeigt, welche von dem Job in eine Statustabelle geschrieben wird und von dir periodisch ausgelesen wird. Die Webseite kannst ja z.B. alle 5 Sekunden refreshen lassen. Solange ein Job läuft kann der User keinen neuen starten.

Ist der Job fertig, wird das ebenfalls vermerkt und das Ergebnis kann angezeigt werden (in welcher Form auch immer).

Dim

Geschrieben

Hallo,

es ist die Frage wie aktuell die Daten sein müssen, Du kannst den Job zeitgesteuert starten und die Daten entsprechend vorbereiten. Eine vernünftige Indizierung hilft. Stored Procedures sind schneller, wie wenn Du alle Anfrage aus dem Programm durchführst. Es wäre ebenfalls zu überlegen, ob Du ein anderes DBMS einsetzte, z.B. bietet Postgres eine gute Fuzzylogik für Volltextsuche. Evtl versuchst Du Deine Daten auch automatisiert zu klassifizieren / clustern, so dass Du nur die Cluster komplett lesen musst, wenn eine Anfrage rein kommt. Performancetechnisch könntest Du auch einen Datenbankcluster aufsetzen. Schau Dir aber auch Deine Statements einmal an, häufig sind diese nicht optimal (über alls ein Select *, auch wenn nur ein Feld benötigt wird). Ebenso prüfe noch einmal die Dabellenstrukturen, befinden sie sich in der 3. Normalform, sind Schlüssel korrekt definiert und verwendet, etc.

Phil

Geschrieben
Stored Procedures sind schneller, wie wenn Du alle Anfrage aus dem Programm durchführst.

Das kann man so pauschal nicht sagen. Sofern man nicht einen extrem schlechten DB-treiber verwendet, ist im Prinzip kein Unterschied wie ein SQL zur Ausführung gebracht wird - es läuft beidemale innerhalb des Servers.

Unterschiede können sich im Ausführungsplan ergeben, was aber dann andere Gründe hat.

Grundsätzlich bin ich jedoch ein klarer Befüworter von SP. Nicht unbedingt aus Performance sondern aus Kapselungs- und Sicherheitsgründen.

Dim

Geschrieben

Hallo,

Das kann man so pauschal nicht sagen. Sofern man nicht einen extrem schlechten DB-treiber verwendet, ist im Prinzip kein Unterschied wie ein SQL zur Ausführung gebracht wird - es läuft beidemale innerhalb des Servers.

Hatte das Problem mit einem Beta Treiber mal, deswegen kam ich auf den Gedanken

Grundsätzlich bin ich jedoch ein klarer Befüworter von SP. Nicht unbedingt aus Performance sondern aus Kapselungs- und Sicherheitsgründen.

Auf jeden Fall, ich habe so den Eindruck, dass es darum geht, aus Tabelle X in Y Daten zu schieben, da würde sich das auf jeden Fall anbieten und das ganze dann einmal von außen via Cron ansteuern.

An den OP: Wie sehen denn die Tabellenstrukturen, Schlüssel, Verknüpfungen und Statements aus

Phil

Geschrieben

Das Ding besteht hauptsächlich aus 2 Tabellen:

Tabelle logs:

Spalten:

-host VARCHAR(32) <- IP-Adressen

-priority VARCHAR(10) <- Priorität der Meldung (6 verschiedene Zustände)

-datetime DATETIME <- Eintragungszeit

-msg TEXT <- Syslog-Meldung

-seq BIGINT <- Primärschlüssel

host, msg, datetime haben nen INDEX

Tabelle dns:

ip VARCHAR(32) <- IP-Adressen, gleichzeitig Primärschlüssel

dns VARCHAR(50) <- DNS-Name zur entsprechenden IP

cat VARCHAR(50) <- IPs können in Kategorien geordnet werden

Eine typische Frage könnte so aussehen:

SELECT l.host,l.priority,l.datetime,l.msg,d.cat,d.dns FROM logs l INNER JOIN dns d ON l.host = d.ip WHERE l.host IS NOT NULL AND l.datetime BETWEEN '2008-05-14 00:00:00' AND '2008-05-14 23:59:59' AND d.dns LIKE 'hier steht der dns-name' ORDER BY l.datetime LIMIT 0,400

Verbesserungsvorschläge?

Geschrieben
Verbesserungsvorschläge?

Ja ein paar:

WHERE l.host IS NOT NULL
Die Bedingung kannst dir sparen, denn bei einem INNER JOIN werden NULL Werte nicht berücksichtigt (mal davon abgesehen, dass ein PK nie NULL sein kann). Auch ist NULL immer ungleich NULL. HOST und DATETIME sollten in einem zusammengesetzten Index indiziert sein. Damit kann in einem lesevorgang gejoint und eingeschränkt werden.
AND d.dns LIKE 'hier steht der dns-name'
Ist das tatsächlich eine LIKE Bedingung mit Jokerzeichen oder in Wirklichkeit eine verborgende = Bedingung? In diesem Fall sollte auch ein = verwendet werden. Wenn über msg wahlfrei gesucht werden soll, würde ich eine Volltextindizierung verwenden. Bei einem LIKE '%text%' kann der Index nicht verwendet werden. Nur wenn Du LIKE 'text%' schreibst. Die bereits vorgeschlagene Partitionierung ist auch eine Möglichkeit. Ich würde das Datum mal als möglichen Partitionsschlüssel ins Auge fassen.
ip VARCHAR(32)

Überleg dir, ob Du die IP als Zahl speichern (Punkte vor dem Einfügen entfernen) und die "echte" IP in einem extra Feld ablegen. Das hätte den Vorteil, dass der Index viel kleiner wird und die DB deshalb weniger verarbeiten muss. Die Berechnugn der Indexgröße bei mysql sieht etwa so aus: (länge+4)/0.67.

Das wären bei 100 Mio IP-Adressen mit durchschnittlich sagen wir 12 Zeichen immerhin über 1,1GB. bei einem Integer wären es nur ca. 770MB. Also schon mal 30% weniger zu lesen bei einem Join.

Problematisch wirds allerdings wenn ipv6 kommt, denn der größte nummerische Datentyp in mysql ist BIGINT und mit 64 Bit leider nur halb so breit wie benötigt. Überleg dir den Schritt also gut. Ist sowieso eher der letzte Schritt.

Dim

Geschrieben

@Amstelchen:

Auf der Kiste läuft MySQL 5.0.41. Also leider keine Partitionierung möglich.

Warum host ein VARCHAR(32) ist kann mir nur Gott sagen :-)

Die DB wurde nicht von mir aufgesetzt. Vllt. 32 damit fast eine IPv6-Adresse reinpassen könnte ;-)

@Dimitri:

Ich habe die Werte mal angepasst. Also "WHERE l.host IS NOT NULL" rausgeworfen und die "LIKE"s durch "=" ersetzt.

Ein Index über HOST und DATETIME einen INDEX zu legen würde nur bei dieser speziellen Query was bringen.

SELECT l.host,l.priority,l.datetime,l.msg,d.cat,d.dns 

FROM logs l INNER JOIN dns d ON l.host = d.ip 

WHERE l.datetime BETWEEN '2008-05-14 00:00:00' AND '2008-05-14 23:59:59' 

ORDER BY l.datetime LIMIT 0,400

Bei dieser bräuchte ich aber dann noch einen gesonderten INDEX über DATETIME. Seh ich das richtig oder?

Sind viele Indices eigentlich ein Problem?

Geschrieben

Ich habe gerade ein paar Statements mit EXPLAIN laufen lassen und unter "Possible Keys" tauchen immer DATETIME und HOST auf. Interpretier ich das damit richtig, dass es wirklich geschickt und ausreichend wäre nur über diese beiden einen INDEX zu machen?

Geschrieben
Bei dieser bräuchte ich aber dann noch einen gesonderten INDEX über DATETIME. Seh ich das richtig oder?

Wieso? das ist doch praktisch das gleiche. Über ip und host wird gejoint und das Datum ist die wohl am meisten einschränkende Bedingung.

Sind viele Indices eigentlich ein Problem?

Sie verlangsamen DML Befehle, da sie natürlich immer mitgepflegt werden müssen.

Interpretier ich das damit richtig, dass es wirklich geschickt und ausreichend wäre nur über diese beiden einen INDEX zu machen?

Ich würde diesen zusätzlichen index mal anlegen, da passiert nichts ausser, das es Plattenplatz kostet und Zeit in anspruch nimmt und dann nochmal testen, prüfen ob der Index verwendet wird (wovon ich ausgehe) und ob die Abfragedauer sich verbessert hat.

Dim

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...