Datenbank Abfragen sehr langsam

Wie gesagt. Wir ziehen nun einen externen Dienstleister hinzu und versuchen so eventuelle Unstimmigkeiten aufzuspüren.
Ich bin gespannt...
 
Werbung:
Die werte in v$ sind alle kumulativ, d.h. Du musst die Gesamtdauer in den V$ Views durch die Anzahl der Ausführungen dividieren.

Ich verwende z.B. so eine Abfrage um die langsamsten Abfragen zu finden:

Code:
select *
from (
  select (elapsed_time / 1000000) as "Total Seconds",
         (elapsed_time - cpu_time) / 1000000 as "Wait (s)",
         user_io_wait_time / 1000000 as "IO Waits (s)",
         (cpu_time / 1000000) as "CPU Seconds",
         disk_reads "Disk Reads",
         executions as "Executions",
         concurrency_wait_time / 1000000 as "Concurrency Wait (s)",
         buffer_gets as "Total Gets",
         rows_processed as "Total Rows",
         round(buffer_gets / nullif(rows_processed,0)) as "Gets/Row",
         round(buffer_gets / nullif(executions,0))  as "Gets/Exec",
         (elapsed_time/1000)/ nullif(executions,0) as "ms/exec",
         s.sql_id,
         s.child_number as child#,
         au.username as parsing_user,
         s.last_active_time,
         s.first_load_time,
         s.sql_fulltext
  from v$sql s
    join all_users au on au.user_id = s.parsing_user_id
  where au.username not in ('SYS', 'SYSTEM', 'SYSMAN', 'DBSNMP', 'EXFSYS')
  order by elapsed_time desc nulls last
)
where rownum <= 100;


Kleiner Auszug...
So richtig kann ich dazu allerdings nichts sagen, ob das jetzt gut oder schlecht ist 🤪

1686139171675.png
 
Jein, ist eher ein Insert. Das braucht normalerweise kaum Zeit. Kann natürlich sein, dass es so viele Inserts sind, dass es so lange dauert, aber der Verdacht ist da eher, dass irgendetwas gelockt ist. Du könntest Dir auch mal die Sperren anschauen, die auf den Tabellen liegen.

Hier mal die Abfrage dazu:

Code:
Select ap.POS_WERT_NETTO_NETTO * NVL(NVL(ap.TAGESKURS, ak.TAGESKURS),
  1) Pos_Wert,
  Decode(ap.POS_WERT_BRUTTO, 0, 0, ((1 - (ap.POS_WERT_NETTO_NETTO /
  ap.POS_WERT_BRUTTO)) * 100)) rabatt,
  ak.A_ART,
  ak.A_STATUS || ' - ' || bez.bez_status(ak.A_STATUS) Status_aktuell,
  ak.STATUS_RG || ' - ' || bez.bez_status(ak.STATUS_RG) Status_RG,
  kfm_status.ermittle_status_kopf(i_a_art => a.A_ART, i_jahr => a.JAHR, i_anr =>
  a.ANR, i_datum => :DATUM_2) || ' - ' ||
  bez.bez_status(kfm_status.ermittle_status_kopf(i_a_art => a.A_ART, i_jahr =>
  a.JAHR, i_anr => a.ANR, i_datum => :DATUM_2)) status_stichtag,
  ak.PROJEKT_A_ART,
  ak.PROJEKT_JAHR,
  ak.PROJEKT_ANR,
  ak.PROJEKT_INDEX,
  ak.PROJEKT_STICHWORT,
  ak.VERK_REGION,
  a.KDNR,
  g.NAME1 Kunde,
  b.NAME Branche,
  a.RENR,
  ak.IHRZEICHEN,
  a.PRODUKT_GR,
  a.TEILENR,
  a.GRNR,
  ap.LIEFERTERMIN,
  ak.UNSER_ZEICHEN,
  ak.LANDCODE,
  ak.AUFTRAG_DATUM,
  NVL(ap.KOSTENST, pp.KOSTENST) As kostenst,
  v.NAME1,
  ak.JAHR,
  ak.ANR,
  ap.POSNR,
  NVL(vertrieb.ermittle_durchschnittspreis(ap.SCHLUESSEL),
  ap.POS_WERT_NETTO_NETTO * NVL(NVL(ap.TAGESKURS, ak.TAGESKURS),
  1)) durchschnittspreis,
  ap.BEZEICHNUNG,
  p1.BEZEICHNUNG As BEZEICHNUNG1,
  p2.BEZEICHNUNG As BEZEICHNUNG2,
  ap.MENGE_BESTELLT,
  z.SKONTO,
  seriennummer.suche_snr('AUF_POS', ap.SCHLUESSEL, ',') Seriennummer,
  Decode(ap.STATUS_LI, Null, 'offen', bez.bez_status(ap.STATUS_LI))
  Lieferstatus,
  Decode(ap.STATUS_RG, Null, 'offen', bez.bez_status(ap.STATUS_RG))
  Rechnungsstatus,
  (Select Max(x.LIEFERTERMIN) Lieferdatum From (Select ak.AUFTRAG_DATUM,
      ak.A_STATUS,
      ak.A_ART,
      ak.LIEFERTERMIN
    From AUF_KOPF ak
    Connect By Prior ak.A_ART = ak.MUTTER_A_ART And Prior ak.JAHR =
      ak.MUTTER_JAHR And Prior ak.ANR = ak.MUTTER_ANR
    Start With ak.A_ART = a.A_ART And ak.JAHR = a.JAHR And ak.ANR = a.ANR) x
  Where x.A_ART In ('LI') And
    x.A_STATUS != 7300) Liefertermin_Lieferschein,
  vk_auswertungen.rechnungsdatum_ermitteln(ak.A_ART, ak.JAHR, ak.ANR,
  :DATUM_2) Rechnungsdatum,
  (Select w.KZSTATUS || ' - ' || bez.bez_status(w.KZSTATUS) From WRKOR w
  Where w.A_ART = a.A_ART And w.JAHR = a.JAHR And
    w.ANR = To_Char(a.ANR)) Status_Technik,
  vk_auswertungen.rechnungswert_auftrag(i_a_art => ak.A_ART, i_jahr =>
  ak.JAHR, i_anr => ak.ANR, i_datum_bis => :DATUM_2, i_datum_von => Null,
  i_firmenwaehrung_jn => 'J') Rechnungswert,
  vk_auswertungen.rechnungs_nr_ermitteln(i_a_art => ak.A_ART, i_jahr =>
  ak.JAHR, i_anr => ak.ANR, i_datum_bis => :DATUM_2, i_datum_von => Null,
  i_rechnung_typ => Null) Rechnungsnummern,
  NVL((Select Sum(ar.BETRAG) From AUF_RABATTE ar, RABATT_ARTEN ra
  Where ar.TYP = ra.RABATT_TYP And ra.STAFFEL_RABATT = 'W' And ar.POSNR = -1 And
    ap.A_ART = ar.A_ART And ap.JAHR = ar.JAHR And ap.ANR = ar.ANR),
  0) Wertrabbatte,
  NVL((Select Sum(az.BETRAG) From AUF_ZUSATZ az
  Where az.POSNR = 0 And ap.A_ART = az.A_ART And ap.JAHR = az.JAHR And
    ap.ANR = az.ANR), 0) Zusatzkosten,
  (Select Sum(apos.POS_WERT_NETTO_NETTO * NVL(apos.TAGESKURS, 1))
  From AUF_POS apos
  Where apos.UNTER_POSNR = 0 And ap.A_ART = apos.A_ART And ap.JAHR = apos.JAHR
    And ap.ANR = apos.ANR) Sum_Positionen,
  (ap.POS_WERT_NETTO_NETTO * NVL(NVL(ap.TAGESKURS, ak.TAGESKURS), 1) /
  Decode((Select Sum(apos.POS_WERT_NETTO_NETTO * NVL(apos.TAGESKURS, 1))
  From AUF_POS apos
  Where apos.UNTER_POSNR = 0 And ap.A_ART = apos.A_ART And ap.JAHR = apos.JAHR
    And ap.ANR = apos.ANR), 0, 1, (Select Sum(apos.POS_WERT_NETTO_NETTO *
    NVL(apos.TAGESKURS, 1)) From AUF_POS apos
  Where apos.UNTER_POSNR = 0 And ap.A_ART = apos.A_ART And ap.JAHR = apos.JAHR
    And ap.ANR = apos.ANR)) * NVL((Select Sum(ar.BETRAG)
  From AUF_RABATTE ar, RABATT_ARTEN ra
  Where ar.TYP = ra.RABATT_TYP And ra.STAFFEL_RABATT = 'W' And ar.POSNR = -1 And
    ap.A_ART = ar.A_ART And ap.JAHR = ar.JAHR And ap.ANR = ar.ANR),
  0)) Wertrabattanteil,
  (ap.POS_WERT_NETTO_NETTO * NVL(NVL(ap.TAGESKURS, ak.TAGESKURS), 1) /
  Decode((Select Sum(apos.POS_WERT_NETTO_NETTO * NVL(apos.TAGESKURS, 1))
  From AUF_POS apos
  Where apos.UNTER_POSNR = 0 And ap.A_ART = apos.A_ART And ap.JAHR = apos.JAHR
    And ap.ANR = apos.ANR), 0, 1, (Select Sum(apos.POS_WERT_NETTO_NETTO *
    NVL(apos.TAGESKURS, 1)) From AUF_POS apos
  Where apos.UNTER_POSNR = 0 And ap.A_ART = apos.A_ART And ap.JAHR = apos.JAHR
    And ap.ANR = apos.ANR)) * NVL((Select Sum(az.BETRAG) From AUF_ZUSATZ az
  Where az.POSNR = 0 And ap.A_ART = az.A_ART And ap.JAHR = az.JAHR And
    ap.ANR = az.ANR), 0)) Zusatzkostenanteil,
  bi.bi_ermittle_vk_preis(i_a_art => ap.A_ART, i_jahr => ap.JAHR,
  i_anr => ap.ANR, i_posnr => ap.POSNR, i_unter_posnr => ap.UNTER_POSNR,
  i_tageskurs => NVL(ap.TAGESKURS, ak.TAGESKURS)) VK_Preis,
  bi.bi_ermittle_vk_preis(i_a_art => ap.A_ART, i_jahr => ap.JAHR,
  i_anr => ap.ANR, i_posnr => ap.POSNR, i_unter_posnr => ap.UNTER_POSNR,
  i_tageskurs => NVL(ap.TAGESKURS, ak.TAGESKURS)) -
  NVL(vertrieb.ermittle_durchschnittspreis(ap.SCHLUESSEL),
  ap.POS_WERT_NETTO_NETTO * NVL(NVL(ap.TAGESKURS, ak.TAGESKURS),
  1)) ZUSATZERLOESE
From VK_STATISTIK a,
  AUF_KOPF ak,
  AUF_POS ap,
  KUNDLIEF g,
  BRANCHE b,
  PROJEKT_POS pp,
  AUF_VERTRETER av,
  VERTRETER v,
  TEILE p,
  PRODUKTGRUPPE p1,
  PRODUKTGRUPPE p2,
  AUF_ZAHLBED az,
  ZAHLBED z
Where ak.A_ART(+) = a.A_ART And ak.JAHR(+) = a.JAHR And ak.ANR(+) = a.ANR And
  ap.A_ART = a.A_ART And ap.JAHR = a.JAHR And ap.ANR = a.ANR And
  ap.POSNR = a.POSNR And ap.UNTER_POSNR = a.UNTER_POSNR And g.KDNR(+) = a.KDNR
  And g.KUNDLIEF_C1(+) = a.KUNDLIEF_C1 And b.BRANCHE(+) = g.BRANCHE And
  ak.PROJEKT_A_ART = pp.A_ART(+) And ak.PROJEKT_JAHR = pp.JAHR(+) And
  ak.PROJEKT_ANR = pp.ANR(+) And ak.PROJEKT_INDEX = pp.POS_INDEX(+) And
  ak.PROJEKT_LFD_NR = pp.LFD_NR(+) And ak.A_ART = av.A_ART(+) And
  ak.JAHR = av.JAHR(+) And ak.ANR = av.ANR(+) And av.VERTNR = v.VERTNR(+) And
  ap.TEILENR = p.TEILENR And p.PRODUKT_GR = p1.PRODUKT_GR(+) And
  p.PRODUKT_GR2 = p2.PRODUKT_GR(+) And ak.A_ART = az.A_ART(+) And
  ak.JAHR = az.JAHR(+) And ak.ANR = az.ANR(+) And az.ZBED = z.ZBED(+) And
  av.POSNR(+) = -1 And z.SPRACHE(+) = 'D' And a.LOGIN_USER = User


vor dieser Abfrage wir ein PLSql gestellt:
Code:
VK_STATISTIK_FUELLEN.fuellen_bi('AU',:DATUM_1,:DATUM_2);


Diese Abfrage benötigt ca. 8 bis 10 Minuten für einen Zeitraum von einem Jahr.
Ergebnis sind ca. 1500 bis 1900 Zeilen.


Interessant wäre herauszufinden auf welche gesamte Datenmenge diese Abfrage läuft.
Mir fehlen aber die Kenntnisse daraus ein Select Count zu machen 🙈
 
Ich denke Du musst zuerst die Statements raus suchen, die am "kritischsten" Sinn. Das können entweder die sein die extrem häufig ausgeführt werden oder die, bei denen eine einzelne Ausführung sehr lange dauert.

Da es hier um ein Produkt geht dessen Code ihr nicht unter Kontrolle habt, wird es vermutlich nicht möglich sein die Häufigkeit der Aufrufe zu reduzieren.

Abfragen bei denen einzelne Ausführungen langsam sind, können vermutlich durch das Anlegen von Indizes beschleunigt werden. Dazu muss man sich aber den Execution Plan ansehen. dhxdu... scheint mir ein Kandidat zu sein (ich werde nie verstehen, warum dunkelgraue Schrift auf hellschwarzem Hintergrund irgendwie angenehm zu lesen ist).

Den gespeicherten Plan (bzw. die gespeicherten Pläne) für eine bestimmte SQLID kann man sich so ansehen:

Code:
SELECT plan_table_output  
FROM dbms_xplan.display_cursor(sql_id => 'dhxdhu73b7bbk',  
                               cursor_child_no => null,
                               format => 'ALIAS BYTES COST NOTE ROWS ALLSTATS PREDICATE'))

Die Strategie bei der Optimierung ist, die Anzahl der Gets (=I/O) zu reduzieren. Je weniger Gets es werden, desto schneller wird eine einzelne Ausführung. Es beschleunigt aber auch konkurrierende Ausführungen (weil weniger Speicherzugriffe synchronisiert werden müssen).

Die hohen Werte bei Concurrency Waits (b55awk..., bxxjc... oder 5w5n...) finde ich beunruhigend. Um das zu analysieren müsste man wissen, was das für Befehle sind. Sind das INSERTs, dann liegt das meistens daran, dass konkurrierende Transaktionen die gleichen Werte für einen primary (oder unique) key einfügen wollen.

Wenn es UPDATEs oder DELETEs sind, dann sind es typischerweise Änderungen auf den gleichen Datensätzen.

Langsame DELETE Befehle (Concurrency Waits _oder_ Performance) können auch an fehlenden Indizes auf den Spalten der Fremdschlüssel liegen (wenn Datensätze aus der referenzierten Tabelle gelöscht werden). Nicht indizierte Fremdschlüssel Spalten kann man sich z.B. mit dieser Abfrage anzeigen lassen:

Code:
with fk_columns as (
  select c.table_name, 
         cc.column_name, 
         cc.position as column_position, 
         c.constraint_name as constraint_name,
         pk.table_name as target_table
  from user_constraints c
    join user_cons_columns cc ON c.constraint_name = cc.constraint_name
    join user_constraints pk ON pk.constraint_name = c.r_constraint_name
  where c.constraint_type = 'R'
), index_columns AS (
  select i.table_name, ic.column_name, ic.column_position, i.index_name
  from user_indexes i
    join user_ind_columns ic ON i.index_name = ic.index_name
), missing_indexes AS (
  select fk.table_name, 
         fk.column_name, 
         fk.column_position,
         fk.constraint_name,
         fk.target_table
  from fk_columns fk
    left join index_columns ic
           on ic.table_name = fk.table_name
          and ic.column_name = fk.column_name
          and ic.column_position = fk.column_position
  where ic.index_name is null
)
select table_name,
       target_table as referenced_table,
       'CREATE INDEX IX_'||substr(constraint_name,1,27)||' ON '||table_name||' ('||listagg(column_name, ',') within group (order by column_position)||');' as missing_index_definition,
       'Changing data in '||target_table||' will lock table '||table_name as problem_description
from missing_indexes
group by table_name, target_table, constraint_name
order by table_name;

Alles in allem scheint mir da so viel im Argen zu liegen, dass ihr mit Hilfe aus einem Forum (von "Amateuren") nicht wirklich weiterkommen wirst. Das solltet ihr euch professionellen Support holen, der das vor Ort analysieren kann.
 
Alles in allem scheint mir da so viel im Argen zu liegen, dass ihr mit Hilfe aus einem Forum (von "Amateuren") nicht wirklich weiterkommen wirst. Das solltet ihr euch professionellen Support holen, der das vor Ort analysieren kann.

Genau das ist in Arbeit. Nächste Woche werden wir mal schauen, was da zu machen ist.
 
Ich danke allen Beteiligen, die hier mitgewirkt haben. Es war und ist sehr interessant andere Meinungen dazu zu hören und hat mir persönlich sehr geholfen.

Über weitere Tipps und Hilfen würde ich mich sehr freuen.
 
SELECT plan_table_output FROM dbms_xplan.display_cursor(sql_id => 'dhxdhu73b7bbk', cursor_child_no => null, format => 'ALIAS BYTES COST NOTE ROWS ALLSTATS PREDICATE'))

Ergebnis ist:

SQL_ID dhxdhu73b7bbk, child number 0

DECLARE job BINARY_INTEGER := :job; next_date TIMESTAMP WITH TIME ZONE
:= :mydate; broken BOOLEAN := FALSE; job_name VARCHAR2(128) :=
:job_name; job_subname VARCHAR2(128) := :job_subname; job_owner
VARCHAR2(128) := :job_owner; job_start TIMESTAMP WITH TIME ZONE :=
:job_start; job_scheduled_start TIMESTAMP WITH TIME ZONE :=
:job_scheduled_start; window_start TIMESTAMP WITH TIME ZONE :=
:window_start; window_end TIMESTAMP WITH TIME ZONE := :window_end;
chain_id VARCHAR2(14) := :chainid; credential_owner VARCHAR2(128) :=
:credown; credential_name VARCHAR2(128) := :crednam;
destination_owner VARCHAR2(128) := :destown; destination_name
VARCHAR2(128) := :destnam; job_dest_id varchar2(14) := :jdestid;
log_id number := :log_id; BEGIN dbms_output.disable; begin
wf_proc_121; wf_ok_setzen(121); exception when others then
wf_exception(121,1027); end; dbms_output.enable(NULL); :mydate
:= next_date; IF broken THEN :b := 1; ELSE :b := 0; END IF; END;

NOTE: cannot fetch plan for SQL_ID: dhxdhu73b7bbk, CHILD_NUMBER: 0
Please verify value of SQL_ID and CHILD_NUMBER;
It could also be that the plan is no longer in cursor cache (check v$sql_plan)
 
Die hohen Werte bei Concurrency Waits (b55awk..., bxxjc... oder 5w5n...) finde ich beunruhigend. Um das zu analysieren müsste man wissen, was das für Befehle sind. Sind das INSERTs, dann liegt das meistens daran, dass konkurrierende Transaktionen die gleichen Werte für einen primary (oder unique) key einfügen wollen.

Hier mal 2 Ergebnisse:

Für b55awk7bp6d6r:
BEGIN
MENUE.FUELLE_MENUE_WF(I_ERL_ANZ_JN => :I_ERL_ANZ_JN);
END;

Für bxxjc20u7v4vu:
SELECT AKTION_NR, TITEL, AUS_JN, COUNT(LFD_NR) ANZAHL_OFFEN, COUNT(GELESEN) GELESEN, KENNER, LEISTE FROM (SELECT A.AKTION_NR, NVL(B.TITEL, A.TITEL) TITEL, AUS_JN, A.LFD_NR, A.KENNER, A.LEISTE, (SELECT 'J' FROM EINGANG_GELESEN WHERE BEARBEITER = :B2 AND LFD_NR = A.LFD_NR) GELESEN FROM EINGANGS_KORB A, DEFINITION B WHERE MENUE.USER_ANZEIGEN_JN(A.AN, ERFASSER, :B1 , ERLEDIGT, NULL, NULL) = 1 AND NVL(ERLEDIGT, 'N') = 'N' AND A.AKTION_NR = B.LFD_NR(+) AND NOT (A.AKTION_NR IS NULL AND NVL(B.TITEL, A.TITEL) IS NULL)) GROUP BY AKTION_NR, TITEL, AUS_JN, KENNER, LEISTE ORDER BY 3 DESC
 
Code:
with fk_columns as (
  select c.table_name,
         cc.column_name,
         cc.position as column_position,
         c.constraint_name as constraint_name,
         pk.table_name as target_table
  from user_constraints c
    join user_cons_columns cc ON c.constraint_name = cc.constraint_name
    join user_constraints pk ON pk.constraint_name = c.r_constraint_name
  where c.constraint_type = 'R'
), index_columns AS (
  select i.table_name, ic.column_name, ic.column_position, i.index_name
  from user_indexes i
    join user_ind_columns ic ON i.index_name = ic.index_name
), missing_indexes AS (
  select fk.table_name,
         fk.column_name,
         fk.column_position,
         fk.constraint_name,
         fk.target_table
  from fk_columns fk
    left join index_columns ic
           on ic.table_name = fk.table_name
          and ic.column_name = fk.column_name
          and ic.column_position = fk.column_position
  where ic.index_name is null
)
select table_name,
       target_table as referenced_table,
       'CREATE INDEX IX_'||substr(constraint_name,1,27)||' ON '||table_name||' ('||listagg(column_name, ',') within group (order by column_position)||');' as missing_index_definition,
       'Changing data in '||target_table||' will lock table '||table_name as problem_description
from missing_indexes
group by table_name, target_table, constraint_name
order by table_name;


Ja, da habe ich ich 12 Treffer bekommen:

1686206487264.png


OK, diesmal schwarze Schrift auf weißen Hintergrund :D
 
Das ist schlecht, aber wenigstens ein konkretes Ergebnis.
12 fehlende Indizes!

Es sind also nicht mal die Statistiken, sondern noch eine Ebene darunter. Wie kann das in 2 Jahren nicht gemacht und geklärt worden sein?

Und man muss festhalten:
Diese Abfrage basiert auf definierten FK. Wenn also der Hersteller an der Stelle auch nur etwas geschlampt hat und nicht mal FK definiert hat, liefert dieses Statement auch keine Ergebnisse.

Du solltest Dir jetzt überlegen, wie Du damit umgehst. Technisch bzw. administrativ und gegenüber Anbieter, Dienstleister, ..
 
Die Definition von Schlüsselwerten, Primärschlüssel und Fremdschlüssel sind ein Hauptmerkmal relationaler Datenbanken. Sie bilden die Basis für ein Hauptleistungsmerkmal einer Datenbank, nämlich Datenkonsistenz.
Technisch sind es Constraints (Bedingungen), die beim Einfügen, Ändern oder Löschen eines Datensatzes geprüft werden (von der DB Engine). Um das adäquat leisten zu können, wird idR zu diesen Schlüsseln auch ein Index angelegt.
Ein Index auf einem FK (und PK) ist quasi Pflicht, um hierfür (und andere Merkmale) eine angemessene (schnelle) Prüfung zu erlauben. (Oracle bietet hier ziemlich viele Möglichkeiten.) Viele Anbieter (DB Anbieter) arbeiten heute so, dass bei Erstellung eines Schlüssel Constraints automatisch ein Index angelegt wird. Alle diese Dinge liegen am Ende in der Verantwortung eines Entwicklers, Modellierers und letztlich im Betrieb beim Administrator einer konkreten Installation.
Die Existenz von FK und zugehörigen Indizes ist existentiell für die Funktion (Du leidest mit dem aktuellen Setup (mindestens) unter dem Fehlen von Indizes). Beides, Indizes und FK sind aber nicht zwingend notwendig bzw. nicht automatisch vorhanden.
Definiert ein Entwickler keine FK (oder nicht alle), so werden weder implizit noch explizit Indizes angelegt. Allerdings, auch wenn keine FK definiert sind, können explizit Indizes angelegt worden sein. Ein FK definiert Fremdschlüssel, ein Index unterstützt ihre Nutzung. Ist er ohne FK vorhanden, verrät er u.U. einen undefinierten FK.

Daraus folgt:
Fehlende Indizes anhand definierter FK zu finden und nachträglich anzulegen, ist fast immer gut (besser als nichts). Fehlende Indizes anhand definierter FK zu ermitteln, ist aber keine vollständige Betrachtung des Problems.

Es gibt Anwendungsanbieter, die aus Gründen* (obfuscation) keine oder nicht alle FK anlegen. Diese "fehlenden" FK können also nicht bei der Ermittlung fehlender Indizierung helfen. In diesen Fällen bleibt nichts anderes übrig, als (besonders) langsame Statements einzeln zu analysieren. Was ja auch nicht unbedingt ein Problem ist.

* Das ist relativ bescheuert, weil man sich selbst damit einer großartigen Funktionalität beraubt, es geschieht dennoch.
 
Hier mal 2 Ergebnisse:
Das erste
MENUE.FUELLE_MENUE_WF
ist der Aufruf einer Stored Procedure und relativ nichtssagend. In dieser SP kann ein oder dutzende Statements und wiederum Prozeduraufrufe erfolgen. Einige oder alle davon können besonders langsam sein. Hier muss man sich den Inhalt der Prozedur ansehen.

Das zweite ist ein Aggregat mit einem inline Subselect. Das ist m.E. ungünstig formuliert, hier muss man Ausführungsplan und Indizierung anschauen. Wenn man die Möglichkeit hätte ggF. auch das Statement umstellen.

Aber eins nach dem anderen. Überleg Dir, was Du mit dem Thema Indizierung machst.
 
Werbung:
Hallo zusammen,

ja, ich weiß, die Überschrift ist sehr allgemein gehalten. Also versuche ich mein Problem ein wenig genauer zu beschreiben.

Nach einem Wechsel einer ERP Software, die auf einer MS SQL basierte, haben wir zu einem ERP Programm auf Oracle SQL gewechselt.
Nun tauchen immer wieder Probleme auf, die mir unter MS SQL nicht bekannt waren. Da geht es z.B. um die allgemeine Performance.
Ja, ich kann nachvollziehen, daß sehr komplexe Abfragen auch seine Zeit dauern. Aber ist es normal, daß z.B. eine Abfrage mit Datensätzen 8 bis 15 Minuten dauert?
Manchmal kann es auch noch länger dauern. Hierbei geht es um Auswertungen für einen Zeitraum von einem Jahr. Möchte man z.B. einen Jahresvergleich von gewissen Umsätzen darstellen, ist das fast unmöglich.

Wie soll ich sowas der Geschäftsleitung erklären?
So kann man ehrlich gesagt nicht arbeiten.

Gibt es eine Möglichkeit, die Performance zu kontrollieren?
Hardwareseitig haben wir keine Probleme, da der Server ziemlich gut aufgestellt und neu ist. Genug RAM ist vorhanden und Festplatten sind alle SSD's.
Ja, der Lieferant wurde diesbezüglich schon kontaktiert. Bekomme aber nur Wischi Waschi Antworten.

Wenn jemand Tipps, Tricks oder Anregungen hat, bin ich für jeden Vorschlag dankbar.
Wie gesagt, daß ist hier allles sehr allgemein gehalten.
Falls Informationen fehlen sollten, kann ich diese gerne nachreichen.
Randnotiz: Ich bin kein Oracle SQL Profi!
Hallo,
wurden die Datentypen im ERP system mit den Datentypen in Oracle verglichen? Hat sich da etwas geändert.
Wurden die Datentypen von MS SQL auf Oracle SQL geändert/angepasst?
VG
 
Zurück
Oben