sql >> Databasteknik >  >> RDS >> Oracle

Oracle lagrad procedur, returnerar ref markör kontra associativa arrayer

DBA:s begäran är inte vettig.

Vad DBA nästan säkert tänker på är att han vill minimera antalet SQL till PL/SQL-motorkontextskiften som pågår när du hämtar data från en markör. Men lösningen som föreslås är dåligt inriktad på just detta problem och introducerar andra mycket allvarligare prestandaproblem i de flesta system.

I Oracle sker en SQL till PL/SQL kontextförskjutning när PL/SQL VM ber SQL VM om mer data, SQL VM svarar genom att exekvera satsen ytterligare för att få data som den sedan paketerar och lämnar tillbaka till PL /SQL VM. Om PL/SQL-motorn frågar efter rader en i taget och du hämtar många rader, är det möjligt att dessa kontextförskjutningar kan vara en betydande del av din totala körtid. För att bekämpa det problemet introducerade Oracle konceptet med bulkoperationer åtminstone under 8i-dagarna. Detta gjorde det möjligt för PL/SQL VM att begära flera rader åt gången från SQL VM. Om PL/SQL VM begär 100 rader åt gången, har du eliminerat 99 % av kontextförskjutningarna och din kod körs potentiellt mycket snabbare.

När bulkoperationer väl introducerades fanns det en hel del kod som kunde omfaktoreras för att bli mer effektiv genom att uttryckligen använda BULK COLLECT operationer istället för att hämta rad för rad och sedan använda FORALL loopar för att bearbeta data i dessa samlingar. Efter 10,2 dagar hade Oracle emellertid integrerat bulkoperationer i implicit FOR loopar så en implicit FOR slingan samlas nu automatiskt in i partier om 100 istället för att hämta rad för rad.

I ditt fall är dock användningen av bulkoperationer mycket mindre betydande eftersom du returnerar data till en klientapplikation. Varje anständigt API på klientsidan kommer att ha funktionalitet som låter klienten specificera hur många rader som måste hämtas från markören i varje nätverksresa och dessa hämtningsförfrågningar kommer att gå direkt till SQL VM, inte via PL /SQL VM, så det finns inga SQL till PL/SQL kontextskiften att oroa sig för. Din applikation måste oroa sig för att hämta ett lämpligt antal rader i varje tur-och-retur-- nog att applikationen inte blir för pratsam och flaskhalsar på nätverket men inte så många att du måste vänta för länge på att resultaten ska bli returneras eller för att lagra för mycket data i minnet.

Att returnera PL/SQL-samlingar snarare än en REF CURSOR till en klientapplikation kommer inte att minska antalet kontextskiften som äger rum. Men det kommer att ha en massa andra nackdelar, inte minst minnesanvändning. En PL/SQL-samling måste lagras helt och hållet i process global area (PGA) (förutsatt dedikerade serveranslutningar) på databasservern. Detta är en bit minne som måste allokeras från serverns RAM. Det betyder att servern kommer att behöva allokera minne för att hämta varenda rad som varje klient begär. Det kommer i sin tur att dramatiskt begränsa skalbarheten för din applikation och, beroende på databaskonfigurationen, kan det stjäla RAM-minne från andra delar av Oracle-databasen, vilket skulle vara mycket användbart för att förbättra applikationens prestanda. Och om du får slut på PGA-utrymme kommer dina sessioner att börja få minnesrelaterade fel. Även i rent PL/SQL-baserade applikationer skulle du aldrig vilja hämta all data till samlingar, du skulle alltid vilja hämta den i mindre partier, för att minimera mängden PGA du använder.

Dessutom kommer att hämta all data till minnet göra att applikationen känns mycket långsammare. Nästan vilket ramverk som helst kommer att tillåta dig att hämta data när du behöver den, så om du till exempel har en rapport som du visar på sidor med 25 rader vardera, skulle din applikation bara behöva hämta de första 25 raderna innan du målar första skärmen. Och den skulle aldrig behöva hämta de nästa 25 raderna om inte användaren råkade begära nästa sida med resultat. Om du hämtar data till arrayer som din DBA föreslår, måste du dock hämta alla rader innan din applikation kan börja visa den första raden även om användaren aldrig vill se mer än den första handfullen av rader. Det kommer att betyda mycket mer I/O på databasservern för att hämta alla rader, mer PGA på servern, mer RAM på applikationsservern för att buffra resultatet och längre väntetider på nätverket.



  1. Finns det något sätt att fånga MySQL- och databasfel i PHP?

  2. Entity Framework Code Först med SQL Server-synonymer

  3. SQL join ON inte lika i Mysql

  4. Hur ansluter man till IPv6-adresser i Kubernetes som körs på Google Container Engine?