Hvad der er galt med markører er, at de ofte bliver misbrugt, både i Oracle
og i MS SQL
.
Markørerne er til at holde et stabilt resultatsæt, som du kan hente række-for-række. De oprettes implicit, når din forespørgsel køres, og lukkes, når den er færdig.
Selvfølgelig kræver det nogle ressourcer at holde et sådant resultatsæt:locks
, locks
, memory
, endda disk space
.
Jo hurtigere disse ressourcer frigives, jo bedre.
At holde en markør åben er som at holde en køleskabsdør åben
Du gør det ikke i timevis uden at det er nødvendigt, men det betyder ikke, at du aldrig skal åbne dit køleskab.
Det betyder, at:
- Du får ikke dine resultater række for række og summere dem:du kalder
SQL
sSUM
i stedet. - Du udfører ikke hele forespørgslen og får de første resultater fra markøren:du tilføjer en
rownum <= 10
betingelse for din forespørgsel
osv.
Hvad angår Oracle
, at behandle dine markører i en procedure kræver berygtet SQL/PLSQL context switch
hvilket sker hver gang du får et resultat af en SQL
forespørg ud af markøren.
Det involverer at sende store mængder data mellem tråde og synkronisere trådene.
Dette er en af de mest irriterende ting i Oracle
.
En af de mindre indlysende konsekvenser af denne adfærd er, at triggere i Oracle bør undgås, hvis det er muligt.
Oprettelse af en trigger og kalder en DML
funktion er lig med at åbne markøren ved at vælge de opdaterede rækker og kalde triggerkoden for hver række af denne markør.
Alene eksistensen af triggeren (selv den tomme trigger) kan bremse en DML
operation 10 times
eller mere.
Et testscript på 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
sekunder uden en trigger, 17.57
sekunder med en tom trigger, der ikke gør noget.