sql >> Database >  >> RDS >> Oracle

Oracle opgeslagen procedure, retourneert ref cursor vs associatieve arrays

Het verzoek van de DBA slaat nergens op.

Wat de DBA vrijwel zeker denkt, is dat hij het aantal contextverschuivingen van SQL naar PL/SQL-engine wil minimaliseren die plaatsvinden wanneer je gegevens van een cursor haalt. Maar de oplossing die wordt gesuggereerd is slecht gericht op dit specifieke probleem en introduceert andere, veel serieuzere prestatieproblemen in de meeste systemen.

In Oracle vindt een SQL-naar-PL/SQL-contextverschuiving plaats wanneer de PL/SQL-VM de SQL-VM om meer gegevens vraagt, de SQL-VM reageert door de instructie verder uit te voeren om de gegevens te krijgen die het vervolgens verpakt en teruggeeft aan de PL /SQL-VM. Als de PL/SQL-engine rijen één voor één vraagt ​​en u veel rijen ophaalt, is het mogelijk dat deze contextverschuivingen een aanzienlijk deel van uw totale runtime kunnen uitmaken. Om dat probleem aan te pakken, introduceerde Oracle het concept van bulkoperaties al in de 8i-dagen. Hierdoor kon de PL/SQL-VM meerdere rijen tegelijk aanvragen bij de SQL-VM. Als de PL/SQL-VM 100 rijen tegelijk aanvraagt, heeft u 99% van de contextverschuivingen geëlimineerd en loopt uw ​​code mogelijk veel sneller.

Nadat bulkbewerkingen waren geïntroduceerd, was er veel code die kon worden aangepast om efficiënter te zijn door expliciet gebruik te maken van BULK COLLECT bewerkingen in plaats van rij voor rij op te halen en vervolgens FORALL te gebruiken loops om de gegevens in die verzamelingen te verwerken. Tegen de 10,2 dagen had Oracle echter bulkoperaties geïntegreerd in impliciete FOR loops dus een impliciete FOR loop verzamelt nu automatisch bulkverzamelingen in batches van 100 in plaats van rij voor rij op te halen.

In uw geval is het gebruik van bulkbewerkingen echter veel minder belangrijk, aangezien u de gegevens naar een clienttoepassing retourneert. Elke fatsoenlijke API aan de clientzijde zal functionaliteit hebben waarmee de klant kan specificeren hoeveel rijen moeten worden opgehaald van de cursor in elke netwerkrondreis en die ophaalverzoeken gaan rechtstreeks naar de SQL-VM, niet via de PL /SQL VM, dus er zijn geen SQL-naar-PL/SQL-contextverschuivingen om je zorgen over te maken. Uw toepassing moet zich zorgen maken over het ophalen van een geschikt aantal rijen in elke rondreis - genoeg zodat de toepassing niet te spraakzaam en bottleneck op het netwerk wordt, maar niet zo veel dat u te lang moet wachten voordat de resultaten zijn geretourneerd of om te veel gegevens in het geheugen op te slaan.

Het retourneren van PL/SQL-verzamelingen in plaats van een REF-CURSOR naar een clienttoepassing zal het aantal contextverschuivingen dat plaatsvindt niet verminderen. Maar het zal een aantal andere nadelen hebben, niet de minste daarvan is het geheugengebruik. Een PL/SQL-verzameling moet volledig worden opgeslagen in de process global area (PGA) (uitgaande van dedicated serververbindingen) op de databaseserver. Dit is een stuk geheugen dat moet worden toegewezen vanuit het RAM-geheugen van de server. Dat betekent dat de server geheugen moet toewijzen om elke laatste rij op te halen waar elke client om vraagt. Dat zal op zijn beurt de schaalbaarheid van uw applicatie drastisch beperken en, afhankelijk van de databaseconfiguratie, RAM stelen van andere delen van de Oracle-database, wat erg handig zou zijn bij het verbeteren van de applicatieprestaties. En als u geen PGA-ruimte meer heeft, zullen uw sessies geheugengerelateerde fouten krijgen. Zelfs in puur op PL/SQL gebaseerde toepassingen zou je nooit alle gegevens in collecties willen ophalen, je zou ze altijd in kleinere batches willen ophalen om de hoeveelheid PGA die je gebruikt te minimaliseren.

Bovendien zal het ophalen van alle gegevens in het geheugen ervoor zorgen dat de applicatie veel langzamer aanvoelt. Met bijna elk framework kunt u gegevens ophalen wanneer u ze nodig hebt, dus als u bijvoorbeeld een rapport heeft dat u in pagina's van elk 25 rijen weergeeft, hoeft uw toepassing alleen de eerste 25 rijen op te halen voordat u de afbeelding schildert. eerste scherm. En het zou nooit de volgende 25 rijen hoeven op te halen, tenzij de gebruiker toevallig de volgende pagina met resultaten opvroeg. Als u de gegevens echter in arrays ophaalt zoals uw DBA voorstelt, moet u alle rijen ophalen voordat uw toepassing de eerste rij kan weergeven, zelfs als de gebruiker nooit meer wil zien dan de eerste handvol rijen. Dat betekent veel meer I/O op de databaseserver om alle rijen op te halen, meer PGA op de server, meer RAM op de applicatieserver om het resultaat te bufferen en langer wachten op het netwerk.



  1. Hoe selecteer je 200 records voor elke 'for loop'-iteratie in Oracle?

  2. MySQL:controleer of de gebruiker bestaat en laat deze vallen

  3. De Optimizer in Oracle Database 19c

  4. gegevens opslaan in een database met behulp van tekst bewerken en knop