Quello che non va con i cursori è che vengono spesso usati in modo improprio, sia in Oracle e in MS SQL .
I cursori servono a mantenere un set di risultati stabile che puoi recuperare riga per riga. Vengono creati implicitamente quando viene eseguita la query e chiusi al termine.
Ovviamente mantenere un tale set di risultati richiede alcune risorse:locks , latches , memory , anche disk space .
Più velocemente queste risorse vengono liberate, meglio è.
Tenere aperto un cursore è come tenere aperta la porta di un frigorifero
Non lo fai per ore senza necessità, ma ciò non significa che non dovresti mai aprire il frigorifero.
Ciò significa che:
- Non ottieni i risultati riga per riga e li sommi:chiami
SQLèSUMinvece. - Non esegui l'intera query e ottieni i primi risultati dal cursore:aggiungi un
rownum <= 10condizione alla tua richiesta
, ecc.
Come per Oracle , l'elaborazione dei cursori all'interno di una procedura richiede il famigerato SQL/PLSQL context switch cosa che accade ogni volta che ottieni un risultato di un SQL query fuori dal cursore.
Implica il passaggio di grandi quantità di dati tra i thread e la sincronizzazione dei thread.
Questa è una delle cose più irritanti in Oracle .
Una delle conseguenze meno evidenti di tale comportamento è che i trigger in Oracle dovrebbero essere evitati, se possibile.
Creazione di un trigger e chiamata a un DML la funzione è uguale ad aprire il cursore selezionando le righe aggiornate e richiamando il codice di attivazione per ogni riga di questo cursore.
La semplice esistenza del trigger (anche il trigger vuoto) può rallentare un DML operazione 10 times o più.
Uno script di prova su 10g :
SQL> CREATE TABLE trigger_test (id INT NOT NULL)
2 /
Table created
Executed in 0,031 seconds
SQL> INSERT
2 INTO trigger_test
3 SELECT level
4 FROM dual
5 CONNECT BY
6 level <= 1000000
7 /
1000000 rows inserted
Executed in 1,469 seconds
SQL> COMMIT
2 /
Commit complete
Executed in 0 seconds
SQL> TRUNCATE TABLE trigger_test
2 /
Table truncated
Executed in 3 seconds
SQL> CREATE TRIGGER trg_test_ai
2 AFTER INSERT
3 ON trigger_test
4 FOR EACH ROW
5 BEGIN
6 NULL;
7 END;
8 /
Trigger created
Executed in 0,094 seconds
SQL> INSERT
2 INTO trigger_test
3 SELECT level
4 FROM dual
5 CONNECT BY
6 level <= 1000000
7 /
1000000 rows inserted
Executed in 17,578 seconds
1.47 secondi senza trigger, 17.57 secondi con un trigger vuoto che non fa nulla.