sql >> Databasteknik >  >> RDS >> Oracle

Vad är det för fel på Cursors?

Det som är fel med markörer är att de ofta missbrukas, både i Oracle och i MS SQL .

Markören är till för att hålla en stabil resultatuppsättning som du kan hämta rad för rad. De skapas implicit när din fråga körs och stängs när den är klar.

Att behålla en sådan resultatuppsättning kräver naturligtvis vissa resurser:locks , locks , memory , även disk space .

Ju snabbare dessa resurser frigörs, desto bättre.

Att hålla en markör öppen är som att hålla en kylskåpsdörr öppen

Du gör det inte i timmar utan att det är nödvändigt, men det betyder inte att du aldrig ska öppna ditt kylskåp.

Det betyder att:

  • Du får inte dina resultat rad för rad och summerar dem:du anropar SQL s SUM istället.
  • Du kör inte hela frågan och får de första resultaten från markören:du lägger till ett rownum <= 10 skick för din fråga

osv.

När det gäller Oracle , att bearbeta dina markörer i en procedur kräver ökända SQL/PLSQL context switch vilket händer varje gång du får ett resultat av en SQL fråga ut från markören.

Det innebär att skicka stora mängder data mellan trådar och synkronisera trådarna.

Detta är en av de mest irriterande sakerna i Oracle .

En av de mindre uppenbara konsekvenserna av det beteendet är att utlösare i Oracle bör undvikas om möjligt.

Skapa en utlösare och anropa en DML funktionen är lika med att öppna markören genom att välja de uppdaterade raderna och anropa triggerkoden för varje rad på denna markör.

Bara existensen av utlösaren (även den tomma utlösaren) kan bromsa en DML operation 10 times eller mer.

Ett testskript 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 utan trigger, 17.57 sekunder med en tom utlösare gör ingenting.



  1. Returnera rad med maxvärdet för en kolumn per grupp

  2. Hur man får och beställer de mest relevanta posterna från databasen med flera nyckelord Laravel 5

  3. Förbisedda T-SQL-ädelstenar

  4. Hur tar man bort poster i tabellen som upprepas?