Newsgroup: it.comp.software.database
Titolo: Prestazioni con Oracle

Salve a tutti,
    sto usando oracle (personal oracle 7.3xx) per implementare un database
accessibile via ODBC e ho gravi problemi di velocità. Per ora sto usando
solo SQLPlus per le prove, ma ottengo dei tempi di ricerca altissimi per una
select con un paio di outer join.
Esempio:
SELECT A.DESCRIZIONE, B.DESCRIZIONE
FROM A, B, AB
WHERE 
A.PK
 = AB.PK_A (+)
      AND 
B.PK
 (+) = AB.PK_B
dove A (PK INTEGER, DESCRIZIONE VARCHAR2(100) ) circa 10000 righe
          B (PK INTEGER, DESCRIZIONE VARCHAR2(100) ) circa 20 righe
          AB (PK_A INTEGER, PK_B INTEGER)                        circa 4000
righe
AB rappresenta un link molti a molti sulle tabelle A e B.
Il risultato è correttamente una view con tutte le righe di A e le relative
B. Es.
AUTO 1    CAMBIO AUTOMATICO
AUTO 1    SERVOSTERZO
AUTO 2    SERVOSTERZO
AUTO 3    <NULL>
Problema: la view è leeenta! Pensavo di utilizzarla con un WHERE DESCRIZIONE
= 'AUTO X' per ogni auto per popolare una lista a video dall'applicazione
client. Inutile dire che ci metterebbe almeno 3 o 4 minuti (sembra che ogni
volta oracle generi tutte le righe della vista e poi le filtri)....
Del resto non so come generare una vista 'dinamica' del tipo VISTA('AUTO 1')
che faccia eseguire una select del tipo
SELECT A.DESCRIZIONE, B.DESCRIZIONE
FROM A, B, AB
WHERE 
A.PK
 = AB.PK_A (+)
      AND 
B.PK
 (+) = AB.PK_B
       AND A.DESCRIZIONE = 'AUTO 1'
In Access facevo così e tutto sembrava funzionare (l'ottimizzatore filtrava
PRIMA A e poi analizzava i link).
Anche eseguendo questa select direttamente dal client (cosa che non mi
piace, vorrei che il database mascherasse il più possibile la sua
struttura), i tempi di risposta non sono soddisfacenti.
Devo per forza create una tabella C con i risultati della view una volta per
tutte e rinunciare al modello relazionale?
Aiuto! :-)

Verifica innanzitutto con quale driver ODBC stai lavorando, il driver
fornito da MS e' circa 6 volte piu' veloce di quello distribuito con Oracle
(non chiedermi perche' che non lo so).
Considera poi che fare una Outer Join tra 3 tabelle e' un macello, forse ti
conviene fare una view tra la tabella AB e la B e fare una sola Outer Join.
Davide

Penso che non sarà mai veloce come tu pretendi, così com'è la struttura
non ha un gran che senso
è impensabile che possa essere veloce con due outher join così messe. Se
fossi in te prima ripenserei alla struttura del DataBase poi si potrà
riparlare della select.
Non è assolutamente il caso che tu crei una tabella C peggiori la
situazione, il problema sta nella tabella AB. Se mi spieghi meglio che
cosa deve contere il DB se voui ti posso dare una mano nel cercare una
soluzione. 
Ciao
Michele
P.S.: Fortunatamente Oracle non è Access

 FROM NOMETABELLA1 A, NOMETABELLA2 B, NOMETABELLA3 AB



B.PK
, AB.PK_B, A.DESCRIZIONE (vedi CREATE INDEX ...)
Più che altro qui occorre un package pl-sql (che lavora direttamente in SGA
ed accetta parametri) o una revisione dell' architettura delle tabelle...
Bye, Ste


pl-sql, si deve fare un package (o una stord-procedure, o una funzione)
per ottenere cose del genere; tramite l' oo4o non hai problemi a
richiamarli anche da VB e/o Access....
Bye, Ste

 ed accetta parametri) o una revisione dell' architettura delle tabelle...
da oracle 8, the complete reference, capitolo 36 (guida all'oracle
optimizer), Operation that performs join:
... non ho voglia di ricopiarlo, comunque e' un ottimo libro, sintetizzo
come da precedente messaggio: mettere indici nei campi interessati dal
join, questo consente ad oracle di scegliere un metodo di nested loop
piuttosto che merge join
comunque, se si vuole ottimizzare un po' evitando il parsing della
stringa sql e l'ottenimento del piano di query (per quello che richiede,
poi...) io farei una vista piuttosto che una procedura

 >
questo non l'avevo visto:
si fa con:
CREATE OR REPLACE VIEW AUTO1 AS
  SELECT A.DESCRIZIONE, B.DESCRIZIONE
  FROM A, B, AB
  WHERE 
A.PK
 = AB.PK_A (+)
        AND 
B.PK
 (+) = AB.PK_B
        AND A.DESCRIZIONE = 'AUTO 1'
WITH CHECK OPTION
l'ultima riga (with check option) serve se la vista e' basata su
un'altra vista
Poi (scusa la banalita' ma non so fino a che punto conosci oracle), devi
creare un public synonym e quindi garantire almeno privilegio di select
all'utente


E come fai a passare un parametro ad una vista ? Comunque
una stored procedure non "parsa" la stringa sql, i parametri
servono proprio a mantenere l' ottimizzazione.
Bye, Ste

WITH CHECK OPTION
Cerca di quotare correttamente, non era mio
il riferimento alla CREATE VIEW (o rispondi
al post corretto....)
Bye, Ste

 servono proprio a mantenere l' ottimizzazione.
non so che linguaggi usi per programmare; normalmente, una stored
procedure si richiama con una SQL, che a differenza di una select o
altro e' dipendente dal DBMS.
oltretutto molti linguaggi consentono di fare un pre-parsing della
stringa SQL (in java, ad esempio, la classe java.sql.PreparedStatement)
chiusa questa breve parentesi, se ti rileggi il thread, capirai che:
la query in access veniva eseguita veloce perche' c'erano gli indici (li
mette in automatico access);
in oracle gli indici mancavano e le prestazioni erano decisamente
peggiori.
quanto all'altro messaggio, in un newsgroup i messaggi sono pubblici,
rispondere all'uno o all'altro e' solo una questione di comodita'
-- 
Greetings,
Alessandro
Pesaro, Italy

 conviene fare una view tra la tabella AB e la B e fare una sola Outer
Join.
Provato, guadagni qualcosina ma non cambia un granché. L'unica soluzione
ganza che ho trovato č stata quella di chiedere l'intera tabella risultante
dalla query e, leggendola riga per riga, discriminare da codice il salto di
record su A (cambio auto).
Insomma ho eliminato il WHERE e ho creato una view che unisce le tabelle.
Certo č scomodo...
P.V.

 P.S.: Fortunatamente Oracle non è Access
Già, lavorando in rete access non è nemmeno da prendere in considerazione.

 come ulteriore suggerimento: non usare A,B,AB ma piuttosto degli alias
Era un esempio :-) Mai mi sognerei di usare nomi tipo "A" per una tabella
:-))
Sono agli inizi con Oracle, ma non proprio alle prime armi per il resto.
P.V.

 E come fai a passare un parametro ad una vista ?
Esattamente il mio problema. Non riesco a farlo con Oracle. Magari non c'è
ne è bisogno, ma venendo da Access trovavo comode le sue query: un qualcosa
a metà tra sp e view che implementano una solta di view parametrizzata.
L'idea originale era di richiamare una ViewAccessori('AUTO n') che fornisse
un set di record (come una view).
P.V.

 richiamarli anche da VB e/o Access....
Uhm, ho giocato un poco con pl-sql, e ho visto che è possibile eseguire
codice sql dinamico. Il guaio è che non so come far restituire alla
procedura un set di righe (come se fosse una view). Devo forse restituire un
parametro di tipo CURSOR? E come lo gestisco da ODBC poi? Ora come ora so
processare solo parametri normali dichiarati OUT da una procedura.
P.V.


No, ci sono precise "regole" su come si lavora su Usenet, regole
che certamente conosci a menadito; semplicemente non è corretto
rispondere alle domande di uno sui post di un'altro, qualcuno potrebbe
pensare che stai cercando di attribuirgli scritti od opinioni che non gli
appartengono.
Saluti, Ste

 indice composto PK_A+PK_B su AB.
da oracle 7.3, puo' ottimizzare in maniera diversa se l'indice non e'
selettivo ed in altre circostanze; prova a mettere esplcitamente
all'interno della query un hint: es, un
select /*+ FIRST ROWS */ ...
ottimizza per ritornare al piu' presto qualcosa piuttosto che la
velocita' complessiva.
un indice doppio, come hai usato te, deve comunque avere come prima
colonna quella piu' selettiva, altrimenti puo' essere piu' efficiente
usare due indici singoli; un indice doppio non ti serve (non viene
usato) per clausole where contenenti una sola delle due colonne
se vuoi toglierti ogni dubbio, usa il comando "explain plan" per vedere
come oracle esegue la query (io continuo a pensare che non vanno bene
gli indici)
