Optimierung der Performace möglich?

DaBuddy

Grünschnabel
Hi Leute,

vor einigen Tagen kam ich bei folgendem Thema nicht weite (http://www.tutorials.de/relationale...e-10g-mehrere-felder-zieltabelle-updaten.html).
Mittlerweile ist das Problem ja gelöst, aber ich bin mit der Performance noch nicht zufrieden :(

Folgendes Statement läuft ca. 5 Stunden:

SQL:
UPDATE 
(SELECT z.artnummer AS OLD, q.artnummer_neu AS NEW
FROM MDTABLE z
INNER JOIN psm q
ON z.artnummer = q.artnummer_alt
AND z.mandant NOT LIKE '3'
) 
SET OLD = NEW;

In der Zieltabelle befinden sich ca. 4 Mio Datensätze, welche durch die Quelltabelle mit ca. 5.000 Datensätzen abgeglichen/angepasst werden soll.

Meine Idee wäre es Oracle die Suche nach den upzudatenden Datensätzen zu nehmen indem ich mir für jeden der 5.000 Datensätze aus der Quelltabelle ein Updatestatement aufbau?
Ich habe da etwas von "Konkatenation" gelesen, aber ich steig da nicht so recht durch.

Ist das überhaupt der richtige Ansatz oder habt ihr einen besseren Vorschlag?

Grüße
Bastian
 
Zuletzt bearbeitet von einem Moderator:
Hi,

ohne jetzt das Statement genauer anzuschauen, aber hast du auf den benutzten Tabellen richtig Indizes vergeben?
Vorallem bei den zusammen-gejointen-Feldern wären Indizes sehr wichtig.

Grüße,
BK
 
Hi BK,

ja das war der erste Optimierungsansatz.

MDTABLE hat auf Artnummer sowie Mandant einen Index und in der PSM ist auf Artnummer_alt ein Index angelegt.

In der MDTABLE gibt es auch drei Trigger, welche bei Änderungen der Datensätze diese in einer Historientabelle festhalten. Diese benötigen auch noch mal Leistung, aber wurden bereits auch deaktiviert.

Grüße
Bastian
 
Hi,

vielleicht geht das Statement hier besser:
SQL:
UPDATE MDTABLE z INNER JOIN psm q ON z.artnummer = q.artnummer_alt
SET z.artnummer = q.artnummer_neu
WHERE z.mandant != 3;

Weiß nicht genau, was du machen willst, bzw. was das Statement oben eigentlich genau macht, deshalb ist meins mal geraten ;)

Ich denke, dass der JOIN im Subselect der Performance-Killer ist.

Grüße,
BK
 
Zuletzt bearbeitet:
Hehe, also der Join ist sicherlich nicht gerade Performance schohnend, aber anders war es - mit meinen Kenntnissen - nicht möglich ;-)

Dein Statement läuft nun auch schon ne ganze Weile. Ich lass es mal noch laufen, aber so nen wirklich schnelleren Eindruck macht es jetzt nicht. Sorry ;)

Kurz zur Erklärung: Das Script soll aus einer Hilfstabelle (PSM), welche alte und neue Artikelnummern enthält, die Daten mit der Zieltabelle abgleichen und sollte es eine alte Artikelnummer geben, dann wird diese durch die neue ersetzt, sofern es nicht Mandant 3 ist.

Kannst du mir evtl. zeigen wie das mit "Konkatenation" funktioniert? :)

Grüße
Bastian
 
ein paar ungeordnete Kommentare:
- da es sich um Oracle handelt, gibt es eine ganze Reihe schöner Instrumentierungs-Hilfsmittel, um zu bestimmen, was die Ursachen für eine schlechte Performance ist. Die einfachste Variante wäre explain plan, daneben gäbe es weitere Prozeduren des dbms_xplan-Packages, SQL Trace, SQL Monitoring etc. Damit könnte man sich den Ausführungsplan des Statements darstellen lassen und herausfinden, wo der Optimizer möglicherweise Unfug anstellt. Ähnliche Möglichkeiten bieten übrigens auch so ziemlich alle anderen RDBMS (obwohl Oracle in Sachen Instrumentierung mehr anbietet als so ziemlich alle anderen).
- 5 Stunden Laufzeit dürften für das Update von ein paar tausend Sätzen in einer Tabelle mit 4M rows zu viel sein.
- der LIKE-Operator ist ohne wildcard ziemlich witzlos: NOT LIKE '3' sagt nur <> '3'.
- man könnte statt dem join-Update auch eine korrelierte Subquery verwenden:
Code:
update mdtable z
   set z.artnummer = (select q.artnummer_neu
                        from psm q
                       where q.artnummer_alt = z.artnummer)
 where z.mandant NOT LIKE '3'
   and exists (select 1
                 from psm q   
                where q.artnummer_alt = z.artnummer)
- ob diese Variante flotter ist, hängt aber wieder vom verwendeten Plan ab: theoretisch kann der Optimizer durchaus den gleichen Plan für zwei komplett unterschiedlich formulierte Queries verwenden, wenn sie semantisch identisch sind, weil er die Möglichkeit hat, die verwendete Query im Rahmen von Transformationsschritten in etwas umzuwandeln, mit dem er besser zurecht kommt.
- eine sinnvolle Indizierung könnte helfen, wenn der Optimizer den Join mit Nested Loops realisiert. Bei Verwendung eines HASH JOINS ist das weniger relevant. Welche Variante tatsächlich verwendet wird, zeigt wiederum der Ausführungsplan.
- eine Erklärung für Fehlentscheidungen des Optimizers können immer auch falsche Statistiken sein: wenn der Optimizer der Größen der Mengen, mit denen er operiert, nicht korrekt einschätzt, dann kann das zu unerfreulichen Effekten führen. Die Aktualisierung der Statistiken wäre über dbms_stats.gather_table_stats möglich.

Gruß

Martin
 
Bei Oracle und riesigen Tabellen ist es für einmalige Updates manchmal einfacher (und aus Erfahrung schneller), die Tabelle zu ersetzen sofern man die DB für sich alleine hat.

1) Haubttabelle umbennen
2) Ein CREATE TABLE haubttabelle AS SELECT.. über den Join
3) Die Indexe, Constraints etc übernehmen
4) Alte Tabelle löschen
 

Neue Beiträge

Zurück