Co je špatného na kurzorech, je to, že jsou často zneužívány, a to jak v Oracle
a v MS SQL
.
Kurzor slouží k udržení stabilní sady výsledků, kterou můžete načíst řádek po řádku. Jsou implicitně vytvořeny při spuštění vašeho dotazu a uzavřeny, když je dokončen.
Uchování takové sady výsledků samozřejmě vyžaduje určité zdroje:locks
, latches
, memory
, dokonce i disk space
.
Čím rychleji se tyto zdroje uvolní, tím lépe.
Ponechat otevřený kurzor je jako nechat otevřené dveře chladničky
Neděláte to celé hodiny bez nutnosti, ale to neznamená, že byste nikdy neměli otevírat lednici.
To znamená, že:
- Nedostáváte výsledky po řádcích a nesčítáte je:voláte
SQL
SUM
místo toho. - Neprovedete celý dotaz a získáte první výsledky z kurzoru:připojíte
rownum <= 10
podmínku vašeho dotazu
, atd.
Pokud jde o Oracle
, zpracování vašich kurzorů uvnitř procedury vyžaduje nechvalně známý SQL/PLSQL context switch
což se stane pokaždé, když získáte výsledek SQL
dotaz mimo kurzor.
Zahrnuje předávání velkého množství dat mezi vlákny a synchronizaci vláken.
Toto je jedna z nejvíce dráždivých věcí v Oracle
.
Jedním z méně zřejmých důsledků tohoto chování je, že pokud je to možné, je třeba se vyhnout spouštěcím událostem v Oracle.
Vytvoření spouštěče a volání DML
funkce se rovná otevření kurzoru výběrem aktualizovaných řádků a voláním spouštěcího kódu pro každý řádek tohoto kurzoru.
Pouhá existence spouštěče (dokonce i prázdného spouštěče) může zpomalit DML
operaci 10 times
nebo více.
Testovací skript na 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
sekund bez spouštěče, 17.57
sekund s prázdnou spouští, která nic nedělá.