sql >> Databáze >  >> RDS >> Oracle

Co je špatného na kurzorech?

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á.



  1. Proč ISNUMERIC('.') vrací 1?

  2. Mysql, kde id je v poli

  3. Spring Batch:Nelze zvýšit identitu; vnořená výjimka je com.microsoft.sqlserver.jdbc.SQLServerException:Neplatný název objektu 'BATCH_JOB_SEQ'?

  4. připojení MySQL serveru k NetBeans