sql >> Database >  >> RDS >> Oracle

Wat is er mis met Cursors?

Wat er mis is met cursors is dat ze vaak worden misbruikt, zowel in Oracle en in MS SQL .

Cursor is voor het bijhouden van een stabiele resultatenset die u rij voor rij kunt ophalen. Ze worden impliciet gemaakt wanneer uw zoekopdracht wordt uitgevoerd en gesloten wanneer deze is voltooid.

Het bijhouden van zo'n resultatenset vereist natuurlijk wat middelen:locks , latches , memory , zelfs disk space .

Hoe sneller deze middelen worden vrijgemaakt, hoe beter.

Een cursor openhouden is als een koelkastdeur openhouden

Je doet het niet urenlang zonder noodzaak, maar het betekent niet dat je nooit je koelkast moet openen.

Dat betekent dat:

  • U krijgt uw resultaten niet rij voor rij en somt ze niet op:u roept de SQL aan 's SUM in plaats daarvan.
  • Je voert geen hele query uit en krijgt de eerste resultaten van de cursor:je voegt een rownum <= 10 toe voorwaarde voor uw vraag

, enz.

Wat betreft Oracle , vereist het verwerken van uw cursors in een procedure de beruchte SQL/PLSQL context switch wat elke keer gebeurt als je een resultaat krijgt van een SQL zoek uit de cursor.

Het gaat om het doorgeven van grote hoeveelheden gegevens tussen threads en het synchroniseren van de threads.

Dit is een van de meest irritante dingen in Oracle .

Een van de minder voor de hand liggende gevolgen van dat gedrag is dat triggers in Oracle indien mogelijk moeten worden vermeden.

Een trigger maken en een DML aanroepen functie is gelijk aan het openen van de cursor, het selecteren van de bijgewerkte rijen en het aanroepen van de triggercode voor elke rij van deze cursor.

Alleen al het bestaan ​​van de trigger (zelfs de lege trigger) kan een DML vertragen bewerking 10 times of meer.

Een testscript op 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 seconden zonder trigger, 17.57 seconden met een lege trigger die niets doet.



  1. Snelste controle of rij bestaat in PostgreSQL

  2. SQL:hoe de rijenvolgorde te behouden met DISTINCT?

  3. De naam van een beperking vinden in MySQL

  4. Ontdek waar uw PHP-code vertraagt ​​(prestatieprobleem)