![]() |
Datenbank: MySQL • Version: 4.1.9 • Zugriff über: UniDAC
MySQL Tabelle flotter machen
Mahlzeit zusammen. Wir haben bei einem Kunden Drucker an Waagen gegen ein DB-Log getauscht, dass statt auf Papier die Ausgaben der Waagen protokolliert. Das landet alles in einer Tabelle, die mit einem kleinen Tool gefiltert und gedruckt werden kann. Mittlerweile sind dort so ca. 150k Datensätze aufgelaufen, und - nicht ganz unerwartet - wird das ganze langsamer. Leider stärker als erhofft, so dass ich jetzt nach Mitteln suche, meine Tabelle und Abfragen "aufzupeppen".
Die Tabelle:
Code:
Die Selects dazu sehen alle in etwa so aus:
CREATE TABLE `log` (
`id` int(10) unsigned NOT NULL auto_increment, `machinenr` int(10) unsigned NOT NULL default '0', `printerdate` datetime NOT NULL default '0000-00-00 00:00:00', `packagenr` int(10) unsigned NOT NULL default '0', `charge` int(10) unsigned NOT NULL default '0', `prodname` varchar(255) NOT NULL default '', `prodnr` varchar(10) NOT NULL default '', `weight` decimal(10,2) NOT NULL default '0.00', `rating` char(2) NOT NULL default '', `deviation` decimal(10,2) NOT NULL default '0.00', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Code:
Wobei es vier wählbare Sortierungen gibt, und es kann nach einzelnen Werten in "machinenr", "prodname", "prodnr" und "rating" gefiltert werden (entsprechende Anfügung (vorne) von "AND (field=:valueparam)" an den WHERE-Teil).
SELECT * FROM log
WHERE (printerdate BETWEEN :dts AND :dte) ORDER BY printerdate, packagenr Die möglichen Sortierungen sind: 1) ORDER BY printerdate, packagenr 2) ORDER BY charge, packagenr, printerdate 3) ORDER BY prodname, printerdate, packagenr 4) ORDER BY prodnr, printerdate, packagenr Erwarteterweise ist 3) mit Abstand das langsamte, doch auch die anderen sind zuweilen mit 5-10 Sekunden einfach zu lange unterwegs. Mit ist klar, dass die Tabelle alles andere als gut Indexiert ist, allerdings haben meine Versuche mit diversen Indizes auch nicht so viel verbessert - ich steck da einfach nicht tief genug drin. Leider muss das große Textfeld "prodname" mitgeschlörrt werden, und um ein "SELECT *" komme ich auch nicht herum, da alle Felder in einem Grid angezeigt werden. Daher meine Frage an die DB-Experten hier: Gibt es zumindest schon mal irgend etwas offensichtliches, womit sich der arme Log-Ausdruck-Mitarbeiter etwas entnerven ließe? Dankschö schon mal! |
AW: MySQL Tabelle flotter machen
Schau dir die Ausführungspläne an.
Oft stellt man fest, dass manche Indizes nicht genutzt werden. In bestimmten Konstellationen kann mit Tabellen Partitionierung gearbeitet werden, um die Geschwindigkeit zu erhöhen. |
AW: MySQL Tabelle flotter machen
Etl. einfach auch einfach mal auf eine aktuelle MySQL-Version gehen.
Wie schaut es eigentlich mit dem Speicher aus? Wie viel RAM darf sich den MySQL genehmigen. In den standardinstallation ist das ja teilweise sehr restriktiv so das die DB primär vom erlaubten Speicher ausgebremst wird und keinerlei Infos im RAM halten kann. |
AW: MySQL Tabelle flotter machen
Ich seh da gar keine Indizes. Ist das der Auslieferungsstatus?
Wie sieht der Zugriff aus? Muss gefiltert werden? Oder kann man auch einfach nur munter 150k Datensätze sortieren lassen? Mein Vorgehen wäre: 1. alle der filterbaren (4?) Felder einzeln indizieren. 2. anzunehmen, dass kein Mensch mehr als 1000 Datensätze durchlesen möchte 3. Die Sortierung auf einem Ergebnisset <1000 erst mal vernachlässigen (dürfte da tatsächlich keine Rolle spielen) weiterhin Die Anwender evtl zur Einschränkung der Suchergebnisse "zwingen" > genauerer Filter Analyse per Ausführungsplan lässt sich auch nur schwer ablehnen. Achso: Filter nur per Gleichheit? Oder auch Like, ...? |
AW: MySQL Tabelle flotter machen
@generic: Wie komme ich an die Pläne, und wie kann ich die Nutzung meiner Indizes dann im Zweifelsfall gewährleisten? (Ich bräuchte ja vor allem erst mal sinnvolle Indizes :))
Die Version ist so eine Sache. Der PC incl. MySQL ist vom Kunden beigestellt, das wird eher nicht so einfach möglich sein. Speicher: Der PC hat 2GB MySQL Key Buffer 2MB Sort buffer 212kB InnoDB Buffer pool size 11MB Additional mem Pool size 2MB Bevor ich aber am Server selbst rumdrehe (bzw. das veranlassen muss), glaube ich, dass da Potenzial in Tabelle und Abfrage stecken muss - die sind nämlich damals noch recht naiv entstanden, als erste Gehversuche nach Umstellung von Paradox auf MySQL als Standard-DB hier im Betrieb. Zumindest hoffe ich, dass der aktuelle Zustand hochgradig unoptimal ist :D |
AW: MySQL Tabelle flotter machen
![]() |
AW: MySQL Tabelle flotter machen
Huch, rotes Kästchen :)
Zitat:
Zitat:
Zitat:
2. Es kann sein, dass Listen gedruckt werden sollen, die so eine Länge haben, doch 3. Inwiefern? Zitat:
Zitat:
Danke dir! |
AW: MySQL Tabelle flotter machen
Zitat:
Code:
Liefert:
EXPLAIN SELECT * FROM log
WHERE (printerdate BETWEEN '01-01-2011 00:00:00' AND '01-02-2011 00:00:00') ORDER BY printerdate, packagenr select_type = SIMPLE table = log type = ALL possible_keys = null key = null key_len = null ref = null rows = 167389 (das sind alle) Extra = Using where; Using filesort Leider sagt mir das nicht viel, ausser dass mir "filesort" irgendwie doof klingt. |
AW: MySQL Tabelle flotter machen
Dann setz doch einmal einen Index auf printerdate und wiederhole das Ganze noch einmal. Zumindest die Testabfrage sollte dann schon etwas schneller Ergebnisse liefern, sofern nicht wieder null unter possible_keys gemeldet wird.
|
AW: MySQL Tabelle flotter machen
Der Key wird, laut explain, dann durchaus verwendet, aber wird es subjektiv entweder kaum oder garnicht schneller, wenn ich die Abfrage abschicke :?
(Ich mach das via PC-Anywhere auf dem Server beim Kunden direkt, so dass Netzwerklaufzeiten keine Rolle spielen dürften.) Da war meine Hoffnung auf ein "Wah! Stell einfach mal das und jenes um, und es fluppst - sowas weiss man doch!" leider zu optimistisch hm? :D |
AW: MySQL Tabelle flotter machen
Zitat:
|
AW: MySQL Tabelle flotter machen
Du musst doch (für's erste) einfach nur je einen Index auf jede Spalte setzen, die in WHERE oder ORDER vorkommt. :gruebel:
Anschließend würde ich noch ein aktuelles MySQL 5 nehmen und schauen, dass man wirklich nur die Datensätze holt die man braucht. Wenn der Server dann einigermaßen Ressourcen besitzt, ist da nicht mehr viel zu machen, bei so einer simplen Struktur. Liebe Grüße, Valentin |
AW: MySQL Tabelle flotter machen
@Bernhard: Keine doofe Idee. Das wird aber eher ein Job für über Nacht :)
Alle Spalten indizieren grad getestet, der Gewinn ist aber leider auch wieder nur sehr marginal. Ich werde mal ein Update des Servers anregen. Schade, ich hatte gehofft da gehörig was falsch gemacht zu haben. Ggf. muss ich dann zum äussersten greifen, und die DB Operationen in einen Thread verlagern, um zumindest das UI etwas geschmeidiger zu machen. Danke euch! |
AW: MySQL Tabelle flotter machen
Ist denn wirklich die Abfrage so langsam oder die Darstellung?
Eine so einfache Abfrage einer Ergebnismenge mit 150k Zeilen dürfte eigentlich innerhalb kürzester Zeit ausgeführt werden. |
AW: MySQL Tabelle flotter machen
Angezeigt wird ja immer nur ein Bruchteil (~50 Zeilen) in einem AdvDBGrid, dass imho recht intelligent darstellt. Ich hab das Grid mal abgeklemmt, und es bleibt gefühlt gleich lang, bis die Abfrage zurück. Sowas doofes, das wäre ja noch relativ leicht zu fixen gewesen.
|
AW: MySQL Tabelle flotter machen
Zitat:
Wird das in mySQL tatsächlich sauber umgesetzt? M.E. steht dort: Nimm das Datumsfeld printerdate und schaue, wo es zwischen den Text(!)werten [von] und [bis] liegt. Die Engine wird ja geezwungen, entweder den eigentlich Spaltenwert zu Text zu konvertieren oder die Operanden zu date. Kenne keine mySLQ explain ausgaben, aber die zeigen ja scheinbar, dass kein Index verwendet wird. Vorschlag: Explizite Konvertierung des Datums im Select und ggF. mit dem between spielen, also zerlegen in (für den Optimizer) "einfachere" Kriterien. zu "3. Die Sortierung auf einem Ergebnisset <1000 erst mal vernachlässigen" Wenn dank Filterung das Ergebnisset so klein ist, ist die Sortierung belanglos. Zumindest bei halbwegs aktueller Hardware. Damit wären Indizes auf den Sortierspalten überflüssig. zu "Angezeigt wird ja immer nur ein Bruchteil (~50 Zeilen) in einem AdvDBGri" Das Anzeigen hat nichts damit zu tun, was der SServer alles durchorgeln muss. Wenn Du es sortiert haben willst, kann er ja schlecht hergehen und nur die ersten 50 Datensätze sortieren. 50 Datensätze holen, spart nur den Großteil des Transportes zum Client, nicht die Sortierung von 150k Sätzen. |
AW: MySQL Tabelle flotter machen
> Wird das in mySQL tatsächlich sauber umgesetzt?
Wird es, das ist allerdings ein "Mock" für's EXPLAIN. Im Programm sind alle Werte über Parameter gesetzt, in diesem Fall .AsDateTime. MySQL erkennt Strings in einem gültigen Datumsformat, und konvertiert diese wenn für ein Datumstyp-Feld eingesetzt automatisch. > Wenn dank Filterung das Ergebnisset so klein ist, ist die Sortierung belanglos. Zumindest bei halbwegs aktueller Hardware. Damit wären Indizes auf den Sortierspalten überflüssig. Wie kann ich MySQL denn verständlich machen, erst den WHERE Teil auszuwerten, dann ORDER BY? Tut es das nicht ohnehin schon? Das wäre doch sonst sträflich für ein DBMS. > Das Anzeigen hat nichts damit zu tun, was der SServer alles durchorgeln muss. Wenn Du es sortiert haben willst, kann er ja schlecht hergehen und nur die ersten 50 Datensätze sortieren. vagtler meinte sicherlich die Zeit, die so manche Komponente zum Zeichnen verbrät, wenn man sie reichlich füttert. Listboxen und Treeviews sind da ja z.B. recht anfällig. Das war es dann ja aber auch nicht. |
AW: MySQL Tabelle flotter machen
Ja, ich meinte schon die Differenz zwischen der Dauer der reinen Abfrage und halt der Zeit bis zur Darstellung des gewünschten Ergebnis (also inkl. Transferleistung).
Ich würde das Statement mal in einem entsprechenden Tool (im Zweifelsfall die MySQL Workbench oder auch SQLyog oder was auch immer) ausführen - da sehe ich dann mal wirklich genau, wie lange das Statement als solches braucht. |
AW: MySQL Tabelle flotter machen
Oha, es gibt da einen heftigen Zusammenhang zwischen Größe des Resultsets und Geschwindigkeit. Frage ich alle Daten in einem Zeitraum von 2 Monaten ab (~58.000 Sätze), dauert das reine Ausführen der Query gut 9 Sekunden. Frage ich nach Daten für einen Tag (~950 Sätze), ist das zackig. (Getestet im guten alten MySQL Administrator bzw. Query Browser). Die Zeiten kommen so in etwa auch in meinem Client hin.
Ich vermute dann einfach mal, dass sich da wirklich nicht viel machen lässt. Dann wird auf jeden Fall schon mal das automatische Refresh nach Änderung der Filter rausgeworfen, so dass der Benutzer das manuell auslösen muss. Das ist nämlich das Problem: Während man die Filter einstellt wird einige Male refreshed, und dabei treten natürlich auch unrealistische Bedingungen ein, wie sehr große Zeiträume. Also habe ich gar kein Problem in der DB, sondern viel mehr im UI. Mit solchen Datenmengen hatte ich bislang auch nicht zu arbeiten - man lernt ja doch nie aus :) |
AW: MySQL Tabelle flotter machen
Zitat:
Im UI machst Du ja auch nichts falsch, Du quälst den Server nur durch unnötig großzügige Benutzerfunktionen. |
AW: MySQL Tabelle flotter machen
Das trifft es besser, stimmt. Ich hab das vorhin entsprechend umgebaut, und das ist in dieser Form nun wieder brauchbar zu bedienen. Besten Dank an alle! :dp:
|
AW: MySQL Tabelle flotter machen
Ich versuch mal mit den Grundlagen anzufangen:
So, nachdem wir das grundsaetzliche geklaert haben, hier noch ein paar Praxistipps:
Dann gehen wir mal kurz auf den Server selbst ein: Zitat:
So, jetzt erstmal lesen, bisserl spielen und du wirst feststellen dass das, was du mit MySQL bisher machst eigentlich keine Herausforderung fuer einen DB-Server ist. Wie gesagt, wir haben MySQL-Instanzen im Einsatz (nicht geclustered) die pro Stunde mehr Daten schreiben als du insgesamt hast - von Performance-Problemen keine Spur. Greetz alcaeus |
AW: MySQL Tabelle flotter machen
Hey alcaeus, erstmal dicken Dank, dass du die die Zeit genommen hast für so viel Posting!
Den Optimierungsteil habe ich die Tage mal überflogen, wobei an den Statements und meiner (einen, kleinen schnuckeligen) Tabelle da bis auf die Indizes wohl wirklich nicht so arg viel zu machen ist, da das ja alles so simpel in der Struktur ist, wie es eigentlich geht. Da ist ja nichtmals ein Join drin, keine SPs, 0 Trigger, nix. Von daher werde ich definitiv an den Speichereinstellungen doktorn, das klingt doch sehr vielversprechend! Ich nehme stark an, dass damals dort einfach eine Standardinstallation gemacht wurde, und gut is. Der PC mit dem DBMS ist schon ein älteres Schätzchen, und für ein eigentlich ja völlig "blödes" Log wird der Kunde da kaum in ein Geschoss investieren wollen. Die 2GB sollten aber locker langen, da das Log praktisch nur von einem anderen PC ausgewertet wird, alle paar Wochen mal ein zweiter. Die Datenmenge ist mit bisher ~30MB auch eher winzig, der Index ist, mit Index auf allen potenziell an WHERE und ORDER BY beteiligten Spalten (was letztlich eigentlich fast alle sind) in etwa genau so groß. Da auf der Kiste sonst nur ein Programm zur Kommunikation mit einer SPS läuft, welches praktisch nichts an CPU und RAM verbrät, sollte ich MySQL problemlos >1GB spendieren können, was dann sogar noch genug Luft nach oben wäre. (Mittelfristig wird dort eh die ganze Anlage mal überholt, so Ende des Jahres eventuell, da könnte man dann ja etwas mehr klotzen :)) Dankschö! |
AW: MySQL Tabelle flotter machen
Zitat:
Viel Erfolg dann! Greetz alcaeus PS: gib mir bitte Feedback ob das Buffer-Tuning das Problem behoben hat - das wuerde mich interessieren. |
AW: MySQL Tabelle flotter machen
Wir haben Ewigkeiten mit einer alten Mühle als DB-Server sehr gute Ergebnisse Ergebnisse erzielt. Die CPU-Geschwindigkeit ist nicht primär maßgebend, sondern -wie schon erwähnt- RAM. RAM und nochmals RAM. Da Speicher billig ist, würde ich das OS ausreizen.
|
AW: MySQL Tabelle flotter machen
Södale, Indizes alle da, Sortbuffer und Inno Pool aufgebohrt, und der Unterschied ist schon üppig! Danke!
Man merkt zwar noch, dass da ein Haufen Sätze beteiligt ist, aber bei weitem nicht mehr so behindernd wie zuvor. Ich konnte den Bufferpool allerdings nicht auf 1GB setzen, da hat dann Windows geweint, dass zu wenig Speicher wäre und hat dem MySQL Service gleich mal ganz den Start verweigert :). Aber ich mutmaße mal ganz stark, dass es mit diesen Einstellungen bis zu Generalüberholung der zugehörigen Produktionsanlage (lies: u.a. Neuer Server) zufriedenstellend ist. Ich musste übrigens herzhaft lachen, als ich nochmal genauer auf die Innereien geschaut habe. Die 2GB RAM sind eigentlich die 2GHz der Celeron CPU gewesen, hab ich mich verguckt. Gekrönt von eigentlich 248MB RAM :lol:. Das ist so alt, da wird's glatt schwierig noch Riegel für aufzutreiben - zumindest für einen vertretbaren Kurs. Aber bisher langt der Mops, und ich hab ja auch auf meinem Arbeitsrechner ohne obige Änderungen sehr Lahme Abfragen gehabt. Hach Industrie. Ich glaub wir haben irgendwo sogar noch einen 486er kleinere Dinge erledigen bei einem Kunden. Aber er tut! :) Nochmals besten Dank! Läuft viel besser, und dank nochmals hin gucken weiss ich ja nun wo der Hund begraben liegt. |
AW: MySQL Tabelle flotter machen
Freut mich dass es tut.
Greetz alcaeus PS: Gut dass du das mit den 248 MB RAM erst jetzt festgestellt hast. Ich waere sprachlos gewesen :lol: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:03 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz