Optimierung von Abfragen möglich?

MySQL, PostgreSQL, SQLite
arno_nuehm
Posts: 4
Joined: 2012-04-14 11:21

Optimierung von Abfragen möglich?

Post by arno_nuehm » 2012-04-14 11:43

Hallo Community,

kurz zu meinem Anliegen:
Ich habe mehrere Abfragen für unsere DB (Warenwirtschaft), die ich per Script abarbeiten lassen muss.
Problem: Die Scripte haben eine Laufzeit von zusammen ca. 35min, in den niemand in der Wawi arbeiten kann. :-(
Dies wollte ich nun natürlich optimieren.

Zu unserem Webserver (liegt auf die DB):
Intel Xeon
4 GB RAM
MySQL 5.1.61-0
Apache 2.2.16
Debian

Als erstes habe ich mich dafür mit der Konfig. von Apache und MySQL befasst:
Mit den bekannten Tuningscripten sinnvolle Werte ermittelt und eingestellt --> für`s erste ganz zufrieden, alle Werte im grünen Bereich.
==> Die Scripte sind jetzt auf 25min Laufzeit runter.

Ich habe nun den verdacht, dass auch die Abfrage "optimierungsfähig" sind, leider komme ich da selbst auf keinen grünen Zweig. :-(
Haltet ihr folg. Abfrage für "vernünftig" formuliert oder könnte man diese optimieren?

    UPDATE `products` SET `products_status` = '0' WHERE (SELECT `products_name` FROM `products_description` WHERE `products_id` = `products`.`products_id`) LIKE '%muster%';

    UPDATE `products` SET `products_status` = '0' WHERE (SELECT `manufacturers_name` FROM `manufacturers` WHERE `manufacturers_id` = `products`.`manufacturers_id`) = 'Mustermann' AND (SELECT `products_name` FROM `products_description` WHERE `products_id` = `products`.`products_id`) LIKE '%henri%';

    UPDATE `products` SET `products_status` = '0' WHERE `products_id` = ANY(SELECT `products_id` FROM `products_to_categories` WHERE `categories_id` = (SELECT `categories_id` FROM `categories_description` WHERE `categories_name` = 'Schuhe')) AND ((SELECT `products_name` FROM `products_description` WHERE `products_id` = `products`.`products_id`) LIKE '%Sonne%');

    UPDATE `products_to_categories` SET `categories_id` = '123' WHERE `products_id` = ANY(SELECT `products_id` FROM `products` WHERE `manufacturers_id` = (SELECT `manufacturers_id` FROM `manufacturers` WHERE `manufacturers_name` LIKE 'Mustermann')) AND `products_id` = ANY(SELECT `products_id` FROM `products_description` WHERE `products_name` LIKE '%Schulz%');

    UPDATE `products` SET `products_price` = `products_p_price` * 2.5 WHERE `products_id` = ANY (SELECT `products_id` FROM `products_to_categories` WHERE `categories_id` = ANY(SELECT `categories_id` FROM `categories` WHERE (`parent_id` = ANY(SELECT `categories_id` FROM `categories` WHERE `parent_id` = ANY(SELECT `categories_id` FROM `categories_description` WHERE `categories_name` = 'Socken')) OR `parent_id` = ANY(SELECT `categories_id` FROM `categories_description` WHERE `categories_name` = 'Socken')))) AND `products_p_price` BETWEEN '5' AND '10';

    UPDATE `products` SET `products_price` = `products_uvp` * 0.979 WHERE (SELECT `manufacturers_name` FROM `manufacturers` WHERE `manufacturers_id` = `products`.`manufacturers_id`) = 'Mustermann';

    UPDATE `products` SET `products_price` = `products_p_price` * 1.08 WHERE `products_id` = ANY (SELECT `products_id` FROM `products_to_categories` WHERE `categories_id` = ANY(SELECT `categories_id` FROM `categories` WHERE (`parent_id` = ANY(SELECT `categories_id` FROM `categories` WHERE `parent_id` = ANY(SELECT `categories_id` FROM `categories_description` WHERE `categories_name` = 'Hemden')) OR `parent_id` = ANY(SELECT `categories_id` FROM `categories_description` WHERE `categories_name` = 'Hemden')))) AND (SELECT `manufacturers_name` FROM `manufacturers` WHERE `manufacturers_id` = `products`.`manufacturers_id`) = 'Steiger' AND `products_p_price` BETWEEN '20' AND '50';

Da ich mich gerade erst in das Thema SQL einarbeite, bitte ich die genannten Fragen zu entschuldigen, falls diese eigentlich "zu einfach" sind.
O.g. Abfragen bekomme ich, trotz fast zweiwöchiger Rechereche im Netz, nicht anders formuliert. :-(

Vielen Dank schon jetzt für eure Hilfe!

Gruß
Manu

ddm3ve
Moderator
Moderator
Posts: 1183
Joined: 2011-07-04 10:56

Re: Optimierung von Abfragen möglich?

Post by ddm3ve » 2012-04-14 12:04

Deine Likes sind "Scheisse".

like '%...%' erfordert immer einen full tables scan. Da kann man nicht mehr viel optimieren, ausser man kann darauf verzichten.
Ich würde Dir einen Upgrade auf Mysql 5.5 erstmal anraten.

Dann würde ich das Statement generell umbauen und mich mal mit "Select case" oder Store Procedures befassen.
Die Subselects sind, wenn ich es so auf die schnell richig erkenne nichts anders als ein Join. Alle Statements schreiben in die Tabelle products.

Daher würde ich die abfrage zusammen legen und anhand des Ergebnisses in einem case, unterscheiden und die Daten entsprechend dem Anwendungsfall eintragen.

Siehe dazu: http://dev.mysql.com/doc/refman/5.1/de/ ... tions.html

Wenn du Deinem jeweiligen Statement ein explain voran stellst, erhälst Du eine Ausgabe, wie mysql an der Stelle optimiert.
Zudem wäre die Tabellendefinition noch ganz gut zu wissen, dann könnte man sich grob übrlegen, wie eine optimale Indizierung für just diesen Anwendungsfall aussehen könnte, sofern nicht schon vorhanden.
02:32:12 21.12.2012 und dann sind Deine Probleme alle unwichtig.

arno_nuehm
Posts: 4
Joined: 2012-04-14 11:21

Re: Optimierung von Abfragen möglich?

Post by arno_nuehm » 2012-04-14 12:33

Hallo ddm3ve,

erst einmal vielen Dank für deine Antwort.

Ich hätte da folg. Rückfragen:
ddm3ve wrote:Deine Likes sind "Scheisse".

like '%...%' erfordert immer einen full tables scan. Da kann man nicht mehr viel optimieren, ausser man kann darauf verzichten.

Dachte ich mir schon irgendwie. Ich muss in bestimmten Spalten der Tabelle nach dieser Zeichenkette suchen. Gibt es da eine Alternativlösung?

ddm3ve wrote:Ich würde Dir einen Upgrade auf Mysql 5.5 erstmal anraten.

In wie weit würde ein Upgrade auf MySQL 5.5 denn einen Performancegewinn bringen? Wurden dort Dinge, die meine Abfragen betreffen könnten, verändert?

ddm3ve wrote:Dann würde ich das Statement generell umbauen und mich mal mit "Select case" oder Store Procedures befassen.

Verstehe leider nicht, was du damit meinst.

ddm3ve wrote:Die Subselects sind, wenn ich es so auf die schnell richig erkenne nichts anders als ein Join. Alle Statements schreiben in die Tabelle products.

Soweit klar.

ddm3ve wrote:Daher würde ich die abfrage zusammen legen und anhand des Ergebnisses in einem case, unterscheiden und die Daten entsprechend dem Anwendungsfall eintragen.

Verstehe leider wieder nicht, was du damit meinst. Hast du mal ein banales Beispiel?


Hatte ich mir die Tage schonmal angeschaut, leider mweiß ich nicht, wie ich das in meinem Fall anwenden könnte.

ddm3ve wrote:Wenn du Deinem jeweiligen Statement ein explain voran stellst, erhälst Du eine Ausgabe, wie mysql an der Stelle optimiert.

Soweit klar.

ddm3ve wrote:Zudem wäre die Tabellendefinition noch ganz gut zu wissen, dann könnte man sich grob übrlegen, wie eine optimale Indizierung für just diesen Anwendungsfall aussehen könnte, sofern nicht schon vorhanden.

Tabellentypen sind durchweg MyISAM.
Indizes sind vorhanden auf products_id, manufacturers_id, products_model, products_status

ddm3ve
Moderator
Moderator
Posts: 1183
Joined: 2011-07-04 10:56

Re: Optimierung von Abfragen möglich?

Post by ddm3ve » 2012-04-14 13:23

1. Mit Tabellendefiniton meine ich nicht die Engine sondern das Schema.

Explain bze. describe table;


2.

Ich würd das Select auf eine einzige abfrage um bauen.
Ein paar Beispiee findest Du hier:
http://www.php.de/datenbanken/57681-mys ... ragen.html
http://mysql-tips.blogspot.de/2005/04/m ... ample.html

usw. ich glaube, das bringt nicht viel, wenn ich Dir Dene abfragen entsprechend um baue. Du musst das selber probieren und verstehen, wie das Case funktioniert.

Alternativ, hole dir die Daten z.B. per PHP Script, Perl Script was auch immer.
Da Du ohnehin einen Fulltable Scan je Abfrage fabrizierst, kannst Du auch einfach mal ein select * from .... ausführen und die Daten in einem Loop Entsprechend bearebtien. also nicht 5 mal diee abfrageen and die DB sondern einmal den Datenstamm holen und updaten. Sinnigerweise würde ich es auf einige Blöcke der Daten begrenzen.
Sprich Limit 1,100 danach Limit 101,200 usw.

Damit kannst Du die Last auf mehre Operationen verteilen und treibst den Admin nicht gleich in den Wahnsinn.

Das gleiche kannst Du natürlich auch als Stored Procedure erledigen.
Einen Loop der als select * from ... Limit 1,100 erstmal anfängt, dann untersuchst Du innerhalb des Loops die einzelne Werte untersuchen und entsprechend die Updates los schicken.

Achte darauf, dass Du daraus Bulk Updates machst.

Eine SQL Schulung kann und will ich nun Online und heute nicht abhalten.
Das sprengt den Rahmen ganz erheblich.
Kauf dir dazu ein passendes Buch und beschäftige dich damit.

z.B. Mysql Cookbook und / oder Effective MySQL Optimizing SQL Statements.
Die mehrere Hundert Seiten Tiefgründiges Know How kann ich hier nicht abwickeln.

Fang einfach mal an, kleinere abfragen über das Case ab zu wickeln und erweitere es. Das Theoretische heran gehen, habe ich Dir erklärt.

Übe damit. Ich muss das im Einzelfall auch immer wieder mal ausprobieren.
02:32:12 21.12.2012 und dann sind Deine Probleme alle unwichtig.

arno_nuehm
Posts: 4
Joined: 2012-04-14 11:21

Re: Optimierung von Abfragen möglich?

Post by arno_nuehm » 2012-04-14 13:40

Perfekt, mit diesen nützlichen Tipps komme ich schon gut weiter. :-)

Ich wollte, um Gottes Willen, nicht, dass du hier abfragen für mich formulierst. Wenn ich das selbst hinbekomme, dann habe ich es auch verstanden. Das bringt mich in den meisten Fällen weiter als "abkäsen". ;-)

So, dann heißt es jetzt mal ausprobieren und lernen.

ddm3ve
Moderator
Moderator
Posts: 1183
Joined: 2011-07-04 10:56

Re: Optimierung von Abfragen möglich?

Post by ddm3ve » 2012-04-14 16:28

Nur nch als kleines exemplarisches Beispiel (habs vorhin vergessen mit auf zu nehmen):

Code: Select all

UPDATE `products` SET `products_status` = '0' WHERE `products_id` = ANY(SELECT `products_id` FROM `products_to_categories` WHERE `categories_id` = (SELECT `categories_id` FROM `categories_description` WHERE `categories_name` = 'Schuhe')) AND ((SELECT `products_name` FROM `products_description` WHERE `products_id` = `products`.`products_id`) LIKE '%Sonne%');


Da Du den "Artikel" ja mit 0 updatest, `products_status` = '0' würde ich die Abfrage um eine wehere Bedingung erweitern.
where `products_status` > '0'
Weil Alle Artikel die ggf. schon 0 haben, musst du ja nicht untötigerweise erneut updaten.
Das mit reduzierst Du die Anzahl an updates und die Treffermenge aus dem Select.

In der Gesamtbetrachtung der Indizierung wäre es wichtig zu analysieren welche anfragen herein kommen und in welcher Menge sowie Ausführungszeit diese laufen.
Mysql kann nur einen Index je Select heran ziehen.

Als Beispiel:

Würden bei dir z.B. zig Anfragen kommen.

select * from product where `products_status`> 1 and `categories_id` =123

und für auswertungen oder andere Statments wie z.B.

select * from product where `categories_id` =123 and product_name = 'Sohle'

Dan müsste man rechnersich abwägen, ob bei einer entsprechende Write Rate, ein Index über

`products_status` und`categories_id`
`products_name`> 1 and `categories_id`
Oder nur über `categories_id` oder `products_status` oder `products_name`
Sinn macht.

Das ist sicherlich eine etwas höhere Kunst und der Optimierung und erfordert neben Erfahrung auch ein wenige mathematisches Verständnis.


Bei einem Kunden habe ich entgegen der Erwartungen der Mitarbeiter die am schnellsten ausgeführten SQL Statements optimiert und dabei die CPU Last um 25% gesenkt.

Das Problem war, dass eine Abfrage nur 2 where Bedingungen enthielt eine fortlaufende id und ein Status Titel.
Genau das Statement ist nie aufgefallen, da es innerhalb 120 ms beantwortet wurde.
Allerdings 15 mal Pro Sekunde die Anfrage gestellt wurde.

Eine andere abfrage dauerte rund 25 Sekunden kam jedoch nur alle 10-20 Minuten vor, tauchte jedoch im Slowquerylog auf.

Die 2. Abfrage hatte noch einen 3. Parameter in der Abfrage.

Beim Mengengerüst der Daten konnte ich folgendes feststellen.

Spalte 1 enthielt ca. 3000 eindeutige Einträge,
Spalte 2 ca. 28 000 eineutige einträge
Spalte 3 nur 4

Die Gewichtung war:

Spalte eins hatte eine ausgeglichene Gleichverteilung
Als jeder der eindeutigen Einträge kam etwa gleich oft vor.
Bei spalte 2 war es so ähnlich.
Es gab 3 Spitzenreiter, die ca. 30% des gesamten Bestands betrafen, der rest teilte sich relativ gleichmässig auf.

Spalte 3 hatte
für 3 deindeutige Einträge jeweils zwischen 2-5 Datensätze in der Tabelle
Der 4. eindeutige Wert jedoch machte 99,998% des gesamten Datenbestands aus.

Dier damalige admin ermittelte für sich, dass die langsame Abfrage, j die 3. Spalte zusätzlich hat und legte einen Index darüber an.

Also über 3 Spalten. Da es sich hier auch um Text handelte, wurde der Index länger als 128* Zeichen.
Das Ergebnis war, dass mit dem abschneiden des Index, der Index fast nichts brachte, eil die Indexeinträge fast der gesamtmenge aus der Datentabele entsprach.

* Nagel mich jett nicht fest, habs nicht 100% genau im Kopf ab welcher Stelle der Index abgescnitten wird.


Ende vom Lied war, dass die Schreibopationen noch mehr ausgebremst wurden, das System teilweise zum Stillstand kam, jedoch alle abfragen sich erheblich verlängerten.

Das anpassen des Index auf Spalte 1 und 2 brachte eine Verbesserung der Ausführungszeit der vielen kleinen Selects um ca. 15%. Damit sank die Last, die Schreiboperationen für das Pflegen des Index reduzierten sich extrem um fast 70%
. Dabei beschleunigten sich die updates von ca. 50 ms auf 7 ms.

Das wiederum sorgte dafür, dass die Reads durch den 50ms Lock der Tabelle nicht mehr ausgebremst wurden. Also reduzierte sich das auch nochmals von 15 ms auf rund 5 ms.

Die vermeindlich schlimmen Abfragen von 25 Sekunden dauerten hinterher zwar immer noch zwischen 4-10 Sekunden, profitierten aber hauptsächlich von der gesamtentlastung des Systemes, und nur ein wenig vom Index.

Ich hoffe, Du verstehst worauf ich hier hinaus will.
Indizierung ist gut, aber manchnal macht ein Kombinierter Index über mehrere Spalten Sinn und manchmal lässt man die eine oder andere Spalte in ruhe.

Ich würde an Deiner Stelle mit einem simplen select count() prüfen wie sich das in der Tabelle verhält.

Beispiel aus einer shoping umgebung:

select count(customers_id),count(customers_cid) from customers group by customers_id;

+---------------------+----------------------+
| count(customers_id) | count(customers_cid) |
+---------------------+----------------------+
| 1 | 1 |
| 1 | 1 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 1 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |
| 1 | 0 |

mysql> select count(customers_id),count(customers_cid) from customers group by customers_cid;
+---------------------+----------------------+
| count(customers_id) | count(customers_cid) |
+---------------------+----------------------+
| 4373 | 0 |
| 64 | 64 |
| 1 | 1 |
| 1 | 1 |
+---------------------+----------------------+

Wie Du siehst, die Kunden sind eigenständige Einträge.
Jeder Kunde oder dessen id ist eindeutig.
Das würde ich auch so erwarten.

Hier macht es ggf. noch Sinn einen Index auf den Primar Key zu legen, customer_id, welcher auch für den Primary Key existiert.

customer_cid macht aber keinen sinn zu indizieren, da nur in 66 Fällen eine echte Optimierung erfolgen würde.
Jetzt weiss ich zufällig, dass die 66 Fälle, also die 3 Kundenkathegorien nahezu nie abgefragt werden, das sind gesperrte Kunden.

Entsprechend musst Du beim richtigen Indizieren gedanklich auch ran.

Die Abfrage auf eine Kunden Kathegorie dauert ca. 3ms
Eine Abfrage auf die Kunden Id dauert durch den Index nur rund 0,5 ms

Auf die Kundenid inkl. kat id wird rund 50 mal pro Minute abgefragt, hingegen nur auf die Kathegorie ID erfolgt im Zusammenhang mit der Statistik einmal am Tag.

Ich habe in meinem Konkreten Fall einen Index über beide Spalten angelegt.
Keine signifikante Verbesserung.

Weder beim einen noch beim anderen Statements. aber die Inserts und Updates dauern jetzt rund 0.003 ms länger.

Bei meinem Datenstamm gänzlich unproblematisch. Aber lass das mal 100 000 000 Einträge sein.
02:32:12 21.12.2012 und dann sind Deine Probleme alle unwichtig.

papabaer
Userprojekt
Userprojekt
Posts: 170
Joined: 2009-05-14 17:40
Location: Halle (Saale)

Re: Optimierung von Abfragen möglich?

Post by papabaer » 2012-04-14 17:09

Ich würde nur am Rande (bin kein Datenbankprofi) noch einwerfen, dass ich die Like-Nummer schräg finde. Eine Datenbank ist doch nun gerade nicht dazu da, dass man in einem bestimmten Feld auch noch Strings suchen muss.

Ich kenne deine konrete Datenbank nicht. Entweder, du findest einen Weg das zu durchsuchende Feld aufzulösen und weiter zu normalisieren, um auf das Like zu verzichten (z.B, eine Wörterbuch-Tabelle), oder du erweiterst deine Applikation um einen Suchserver a la Lucene.

ddm3ve
Moderator
Moderator
Posts: 1183
Joined: 2011-07-04 10:56

Re: Optimierung von Abfragen möglich?

Post by ddm3ve » 2012-04-14 19:23

Bei Bereinigunsjobs bleibt oftmals nichts anders übrig als über like zu arbeiten.
Du hast grundsätzlich recht, ein Like verursacht immer einen Full Table Scan.
Hatte ich eingangs schon erwähnt.
Dein Ansatz eine eigene Wörterbuchtable zu nutzen ist sicherlich ein guter Ansatz.
In seinem Fall wird aber schon durch die "Joins" die teilweise existieren ein full Table scan verursacht.

Daher mein Rat, eben diesen einen table scan aktzeptieren und eben keine bis zu 5 verursachen.
Da die genaue Anforderung und Tabellenaufbau nicht bekannt sind, ist eine Optimierungsfindung am Db Design schwierig.

Ich vermute jedenfalls, dass Artikelname und Speziell Katheogirename eher zur anzeige dienen und keine üblichen Suchrkiterien erfüllen.

Falls doch, muss er an das Thema definitiv ran.
Wobei hier dann ggf. eine Volltextsuche eine Option wäre:
http://dev.mysql.com/doc/refman/5.1/de/ ... earch.html

Würde dann nicht gleich den Einsatz neuer Techniken und damit ggf. erhebliche Anpassung der Anwendung erfordern.
Last edited by ddm3ve on 2012-04-14 19:58, edited 1 time in total.
02:32:12 21.12.2012 und dann sind Deine Probleme alle unwichtig.

User avatar
Joe User
Project Manager
Project Manager
Posts: 11137
Joined: 2003-02-27 01:00
Location: Hamburg

Re: Optimierung von Abfragen möglich?

Post by Joe User » 2012-04-14 20:52

ddm3ve wrote:Da Du den "Artikel" ja mit 0 updatest, `products_status` = '0' würde ich die Abfrage um eine wehere Bedingung erweitern.
where `products_status` > '0'

Statt "... > '0'" würde ich eher "... != '0'" verwenden, schliesslich kann theoretisch auch ein negativer Wert vorkommen und es ist zudem auch für andere Admins sofort ohne Codeanalyse erkennbar, worum es geht.

Desweiteren sollte unbedingt so viel Logik wie möglich in die Anwendung verlagert werden, wodurch sich etliche Subqueries/Joins einsparen lassen.

Sind die einzelnen Updates denn überhaupt an der selben Stelle der Anwendung, oder sind sie verschiedenen Aufgaben zugeordnet? Letzteres würde nämlich ein Zusammenlegen der Queries verbieten.

Die Tabellendefinitionen wären trotzdem mal interessant, vielleicht kann man dann die Queries wenigstens schonmal grob entflechten und etwas optimieren.
PayPal.Me/JoeUserFreeBSD Remote Installation
Wings for LifeWings for Life World Run

„If there’s more than one possible outcome of a job or task, and one
of those outcomes will result in disaster or an undesirable consequence,
then somebody will do it that way.“ -- Edward Aloysius Murphy Jr.

ddm3ve
Moderator
Moderator
Posts: 1183
Joined: 2011-07-04 10:56

Re: Optimierung von Abfragen möglich?

Post by ddm3ve » 2012-04-14 21:30

Joe User wrote:Sind die einzelnen Updates denn überhaupt an der selben Stelle der Anwendung, oder sind sie verschiedenen Aufgaben zugeordnet? Letzteres würde nämlich ein Zusammenlegen der Queries verbieten.



Nicht unbedingt, man müsste sich aber dann überlegen diese "Wartungsarbeiten" in einen Service aus zu lagern, der bei bedarf eben durch die Datensätze geht. vieles ist oftmals Request gesteuert.
Das würde ich für schwergewichtige Operationen grundsätzlich überlegen.
Last edited by ddm3ve on 2012-04-14 22:23, edited 1 time in total.
02:32:12 21.12.2012 und dann sind Deine Probleme alle unwichtig.

arno_nuehm
Posts: 4
Joined: 2012-04-14 11:21

Re: Optimierung von Abfragen möglich?

Post by arno_nuehm » 2012-04-14 21:35

ddm3ve wrote:Ich vermute jedenfalls, dass Artikelname und Speziell Katheogirename eher zur anzeige dienen und keine üblichen Suchrkiterien erfüllen.

korrekt.

Joe User wrote:Statt "... > '0'" würde ich eher "... != '0'" verwenden, schliesslich kann theoretisch auch ein negativer Wert vorkommen und es ist zudem auch für andere Admins sofort ohne Codeanalyse erkennbar, worum es geht.

Negativ kann in dieser DB nicht vorkommen, nur 0 (=offline) und 1 (=online).

Joe User wrote:Sind die einzelnen Updates denn überhaupt an der selben Stelle der Anwendung, oder sind sie verschiedenen Aufgaben zugeordnet? Letzteres würde nämlich ein Zusammenlegen der Queries verbieten.

Es handelt es sich um reines Kalkulations- und Updatescript, dass Bezeichnungen von Artikeln (REPLACE()), Artikelstatus (0/1) und Preise verändert.

Joe User wrote:Die Tabellendefinitionen wären trotzdem mal interessant, vielleicht kann man dann die Queries wenigstens schonmal grob entflechten und etwas optimieren.

Welcher Wert interessiert euch denn genau? Da die Tabelle sehr viele Spalten hat, würde ich ungerne alle posten.

An dieser Stelle vielen vielen Dnak für eure Hinweis eund Tipps.
Ich habe jetzt mal ein Testscript aufgesetzt, in dem ich nur noch multi. Arrays und SELECT CASE Anweisungen nutze. Erster Test --> Minderung der Laufzeit um 30%. :-)

Wenn ich ein komplettes Testscript des Originals aufgesetzt habe, poste ich mal die neue Laufzeit.

Noch mal herzlichen Dank!

Gruß
Manu

ddm3ve
Moderator
Moderator
Posts: 1183
Joined: 2011-07-04 10:56

Re: Optimierung von Abfragen möglich?

Post by ddm3ve » 2012-04-14 21:57

Joe User wrote:Desweiteren sollte unbedingt so viel Logik wie möglich in die Anwendung verlagert werden, wodurch sich etliche Subqueries/Joins einsparen lassen.



Da gibt es sehr unterschiedliche Ansichten.
Mit Trigger und strored Procedures, kann die Datenbank sehr simpel mit einer Tabelle
als Schnittstelle fungieren um dennoch zusätzliche Funktionalitäten an zu bieten.

Speziell dann, wenn man keinen Einfluss auf Anwendungen hat und auf eine gemeinsame Datenbasis zugreifen muss.

Die Alte Schule spricht i.d.R. davon die jweiligen Layer nicht zu trennen. Und nicht zu verschmelzen.
Larry (Oracle) hat hier einen anderen Ansatz und sagt sich, es soll dem Anwender frei gelassen werden, wo er seine Funktionalität einbindet.
Allein aus dem Grund heraus, dass sich der Entwickler dann ernsthaft um die Datenbank bemühen muss, und sich damit beschäftigen muss, halte ich für einen guten Ansatz.

Nutzt man OR Mapper benötigt man häufig deutlich mehr Requests zur Datenbank, die meinetwegen etwas simpler sind, als wenn man die Selecs im Vorfeld geziehlt für die nötige Operation in Form von Views, oder eben eigenen SQLs und Joins zusammen fasst.

Jeder Requests kostet Zeit.
Bei komplexeren Systemen, wie ich sie des öfteren erlebe, bleibt es selten aus, dass ein Request auf eine Frontendseite schon mal deutlich mehr ls nur einen Datenbank Request ausführt.

Oben hatte ich einen solchen Fall schon angeschrieben.
Das hies es Anwendung Lahm, der DBA sagte nichts auffälliges.

Am ende waen es wegen Objektberechtigunen und einer ungeschickten aber nicht sonderlich besser zu lösenden Abfolge an Zugrieffprüfungen darauf hinaus gelaufen, dass dieser eine Request 35 SQL Abfragen verursacht hat.

Ermittelt zugriffsrecht, Ermitteln Objekte,
Ermitteln Berechtigung für jedes einzelne Objekt, Laden des jeweiligen Objekts.

Man kann jetzt sicherlich darüber streiten, ob man das nicht mit anderen Techniken hätte lösen sollen. Nach ungefähr 15 Mannjahren Enwicklung wars aber zu spät und nicht mehr refinanzierbar das neu zu machen.
Und as man das Projekt begann, war halt "Toplink" das Wundertool der Wahl.
Später gabs dann auch noch Hibernate. Aber das ist ein anderes Thema.

Das war aber nun ein Offtopik Ausflug zum Architektendasein, was halt bedeutet, da müssten mal alle mit an einen Tisch und Überlegen, wie mans am besten machen kann. Man sollte eine solche Sache nie, nur von einem Standpunkt aus sehen.
Daher back zum Topic, das Schema ist sicherlich Reizvoll, will man da Thema aber ganzheitlich optimieren bzw., bodenständig und vernünftig angehen, müsste man sich eher überlegen einen entsprechenden Architekten einzubinden, der sich mal zwischen der Anforderung, der Umsetzung und dem Nutzerverhalten Überlegt, wie mans anders besser machen kann. Aber bei dem Level befürchte ich fast, ist das Forum allein an Masse des Aufwandes nicht wirklich in der Lage nebenzu zu helfen.
;-) Man kanns natürlich auch Übertreiben, aber das schnellste DBMS bringt mir nichts, wenn die Requests in der Masse und seriellen Ausführung zu lange braucht.

Zunächst ging es aber um ein paar simple SQLs und ob man die Optimieren kann.

Ich fasse daher nochmals zusammen:

Verzicht auf like abfragen
Ergebnissmenge so gut es geht reduzieren.
Keine unnötigen Requests wie Updates auf Tabellen, in denen sich nichts ändern würde.
Joins aufschlüsseln, darauf so gut es geht verzichten.
Indizierung angemessen dem Nutzungsverhalten erstellen.
In den where Bedingungen keine Funktionen aufrufen, das fordert einen Full Tables scan, ähnlich wie like abfragen.
02:32:12 21.12.2012 und dann sind Deine Probleme alle unwichtig.

ddm3ve
Moderator
Moderator
Posts: 1183
Joined: 2011-07-04 10:56

Re: Optimierung von Abfragen möglich?

Post by ddm3ve » 2012-04-14 22:07

arno_nuehm wrote:
Joe User wrote:Statt "... > '0'" würde ich eher "... != '0'" verwenden, schliesslich kann theoretisch auch ein negativer Wert vorkommen und es ist zudem auch für andere Admins sofort ohne Codeanalyse erkennbar, worum es geht.

Negativ kann in dieser DB nicht vorkommen, nur 0 (=offline) und 1 (=online).

Also Joe Uses Einwand ist hier dennoch absolut korrekt.
Auch wenn eine > geringfühgig schneller verarbeitet wird, ist der Untershied zu != kaum Messbar.
Hängt u.a. auch mit dem Indextyp zusammen.

Du solltest auf jeden Fall beachten, ein update bedeutet auf DB / Storage Seite

ein read und 2 writes.
In typischen DMSen wird bei einem update ein neuer Datensatz eingefügt und der alte gelöscht.
Daher möglichst vermeiden, wenn es nicht nötig ist.
02:32:12 21.12.2012 und dann sind Deine Probleme alle unwichtig.