I spĂ„ren av Highload++ Siberia 2019 – 8 uppgifter om Oracle

Hej!

Den 24-25 juni anordnades konferensen Highload++ Siberia 2019 i Novosibirsk. VÄrt team var ocksÄ dÀr. med en presentation »Containerdatabaser Oracle (CDB/PDB) och deras praktiska anvÀndning för programutveckling«, vi kommer att lÀgga ut en textversion lite senare. Det var fantastiskt, tack. olegbunin för arrangemanget, samt alla som kom.

I spĂ„ren av Highload++ Siberia 2019 – 8 uppgifter om Oracle
I det hÀr inlÀgget vill vi dela med oss av de uppgifter som fanns pÄ vÄr monter, sÄ att ni kan testa era kunskaper i Oracle. Nedan följer 8 uppgifter, svarsalternativ och förklaringar.

Vilket Àr det högsta vÀrdet av sekvensen vi kommer att se som resultat av att köra följande skript?

create sequence s start with 1;
 
select s.currval, s.nextval, s.currval, s.nextval, s.currval
from dual
connect by level <= 5;

  • 1
  • 5
  • 10
  • 25
  • Inget, det blir ett fel.

SvarEnligt Oracle-dokumentationen (citerad frÄn 8.1.6):
Inom en enda SQL-sats kommer Oracle att öka sekvensen endast en gÄng per rad. Om en sats innehÄller mer Àn en referens till NEXTVAL för en sekvens, ökar Oracle sekvensen en gÄng och returnerar samma vÀrde för alla förekomster av NEXTVAL. Om en sats innehÄller referenser till bÄde CURRVAL och NEXTVAL, ökar Oracle sekvensen och returnerar samma vÀrde för bÄde CURRVAL och NEXTVAL oavsett deras ordning inom satsen.

DÀrför kommer det högsta vÀrdet att motsvara antalet rader, det vill sÀga 5..

Hur mÄnga rader kommer att finnas i tabellen som resultat av att köra följande skript?

create table t(i integer check (i < 5));
 
create procedure p(p_from integer, p_to integer) as
begin
    for i in p_from .. p_to loop
        insert into t values (i);
    end loop;
end;
/
 
exec p(1, 3);
exec p(4, 6);
exec p(7, 9);

  • 0
  • 3
  • 4
  • 5
  • 6
  • 9

SvarEnligt Oracle-dokumentationen (citerad frÄn 11.2):

Innan nÄgon SQL-sats körs markerar Oracle en implicit savepoint (inte tillgÀnglig för dig). Om satsen misslyckas backar Oracle automatiskt tillbaka och returnerar den aktuella felkoden till SQLCODE i SQLCA. Till exempel, om en INSERT-sats orsakar ett fel genom att försöka sÀtta in ett dubblettvÀrde i ett unikt index, backas satsen tillbaka.

Anropet för lagrad procedur frÄn klienten betraktas ocksÄ och behandlas som en enda sats. SÄledes avslutas det första anropet för den lagrade proceduren framgÄngsrikt och sÀtter in tre poster; det andra anropet för den lagrade proceduren avslutas med ett fel och backar den fjÀrde posten som den har lyckats sÀtta in; det tredje anropet avslutas med ett fel, och i tabellen finns tre poster..

Hur mÄnga rader kommer att finnas i tabellen som resultat av att köra följande skript?

create table t(i integer, constraint i_ch check (i < 3));
 
begin
    insert into t values (1);
    insert into t values (null);
    insert into t values (2);
    insert into t values (null);
    insert into t values (3);
    insert into t values (null);
    insert into t values (4);
    insert into t values (null);
    insert into t values (5);
exception
    when others then
        dbms_output.put_line('Oops!');
end;
/

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

SvarEnligt Oracle-dokumentationen (citerad frÄn 11.2):

En kontrollbegrÀnsning lÄter dig specificera ett villkor som varje rad i tabellen mÄste uppfylla. För att uppfylla begrÀnsningen mÄste varje rad i tabellen göra villkoret antingen SANT eller okÀnt (pÄ grund av null). NÀr Oracle utvÀrderar ett villkor för en kontrollbegrÀnsning för en specifik rad, refererar alla kolumnnamn i villkoret till kolumnvÀrdena i den raden.

SÄledes kommer vÀrdet null att passera kontrollen, och det anonyma blocket kommer att köras fram till försöket att införa vÀrdet 3. DÀrefter kommer felhanteringsblocket att fÄnga undantaget, det kommer inte att bli nÄgon tillbakagÄng och fyra rader kommer att förbli i tabellen med vÀrdena 1, null, 2 och Äterigen null.

Vilka vÀrdepar kommer att ta upp samma mÀngd utrymme i blocket?

create table t (
    a char(1 char),
    b char(10 char),
    c char(100 char),
    i number(4),
    j number(14),
    k number(24),
    x varchar2(1 char),
    y varchar2(10 char),
    z varchar2(100 char));
 
insert into t (a, b, i, j, x, y)
    values ('Y', 'Vanya', 10, 10, 'D', 'Vanya');

  • A och X
  • B och Y
  • C och K
  • C och Z
  • K och Z
  • I och J
  • J och X
  • Alla angivna

SvarLÄt oss ge utdrag frÄn dokumentationen (12.1.0.2) om lagring av olika datatyper i Oracle.

CHAR Datatyp
CHAR-datatypen specificerar en teckenstrÀng med fast lÀngd i databasens teckenkodning. Du specificerar databasens teckenkodning nÀr du skapar din databas. Oracle sÀkerstÀller att alla vÀrden som lagras i en CHAR-kolumn har den lÀngd som anges av storleken i den valda lÀngdsemantiken. Om du infogar ett vÀrde som Àr kortare Àn kolumnens lÀngd, dÄ fyller Oracle upp vÀrdet med mellanslag till kolumnens lÀngd.

VARCHAR2 Datatyp
VARCHAR2-datatypen specificerar en teckenstrÀng med variabel lÀngd i databasens teckenkodning. Du specificerar databasens teckenkodning nÀr du skapar din databas. Oracle lagrar ett teckenvÀrde i en VARCHAR2-kolumn exakt som du anger det, utan nÄgot mellanslagsfyllande, förutsatt att vÀrdet inte överskrider kolumnens lÀngd.

NUMBER Datatyp
NUMBER-datatypen lagrar noll samt positiva och negativa fasta tal med absoluta vÀrden frÄn 1.0 x 10-130 till men inte inklusive 1.0 x 10126. Om du anger ett aritmetiskt uttryck vars vÀrde har ett absolut vÀrde större Àn eller lika med 1.0 x 10126, dÄ returnerar Oracle ett fel. Varje NUMBER-vÀrde krÀver frÄn 1 till 22 byte. Med detta i Ätanke kan kolumnens storlek i byte för ett specifikt numeriskt datavÀrde NUMBER(p), dÀr p Àr precisionen för ett givet vÀrde, berÀknas med följande formel: ROUND((length(p)+s)/2))+1 dÀr s Àr lika med noll om talet Àr positivt, och s Àr lika med 1 om talet Àr negativt.

Dessutom ska vi ta en utdrag ur dokumentationen om lagring av Null-vÀrden.

Ett null-vÀrde Àr avsaknaden av ett vÀrde i en kolumn. Null-vÀrden indikerar saknad, okÀnt eller ovidkommande data. Null-vÀrden lagras i databasen om de ligger mellan kolumner med datavÀrden. I dessa fall krÀver de 1 byte för att lagra lÀngden pÄ kolumnen (noll). Efterföljande null-vÀrden i en rad krÀver ingen lagring eftersom en ny radhuvud signalerar att de ÄterstÄende kolumnerna i den föregÄende raden Àr null. Till exempel, om de tre sista kolumnerna i en tabell Àr null, lagras ingen data för dessa kolumner.

Baserat pÄ dessa data bygger vi resonemang. Vi antar att databasen anvÀnder kodningen AL32UTF8. I denna kodning kommer ryska bokstÀver att ta upp 2 byte.

1) A och X, vĂ€rdet av fĂ€ltet a 'Y' tar 1 byte, vĂ€rdet av fĂ€ltet x 'D' – 2 byte
2) B och Y, 'Vasya' i b kommer att fyllas ut med mellanslag upp till 10 tecken och ta 14 byte, 'Vasya' i d – kommer att ta 8 byte.
3) C och K. BÄda fÀlten har vÀrdet NULL, efter dem finns betydelsefulla fÀlt, sÄ de tar upp 1 byte vardera.
4) C och Z. BÄda fÀlten har vÀrdet NULL, men fÀltet Z Àr det sista i tabellen, sÄ det tar ingen plats (0 byte). FÀlt C tar upp 1 byte.
5) K och Z. PĂ„ samma sĂ€tt som föregĂ„ende fall. VĂ€rdet i fĂ€lt K tar upp 1 byte, i Z – 0.
6) I och J. Enligt dokumentationen kommer bÄda vÀrdena att ta upp 2 byte. LÀngden berÀknas med formeln frÄn dokumentationen: round((1 + 0) / 2) + 1 = 1 + 1 = 2.
7) J och X. VÀrdet i fÀlt J tar upp 2 byte, vÀrdet i fÀlt X tar upp 2 byte.

Sammanlagt, korrekta alternativ: C och K, I och J, J och X.

Vad kommer clustering-faktorn för indexet T_I att vara ungefÀr?

create table t (i integer);
 
insert into t select rownum from dual connect by level <= 10000;
 
create index t_i on t(i);

  • Cirka tiotal
  • Cirka hundratal
  • Cirka tusental
  • Cirka tiotusental

SvarEnligt Oracle-dokumentationen (citeras frÄn 12.1):

För ett B-trÀd index mÀter indexets clustering-faktor den fysiska grupperingen av rader i förhÄllande till ett indexvÀrde.

Indexets clustering-faktor hjÀlper optimeraren att avgöra om en indexscanning eller en full tabellscanning Àr mer effektiv för vissa frÄgor. En lÄg clustering-faktor indikerar en effektiv indexscanning.

En clustering-faktor som ligger nÀra antalet block i en tabell indikerar att raderna Àr fysiskt ordnade i tabellblocken efter indexnyckeln. Om databasen gör en full tabellscanning tenderar databasen att hÀmta raderna i den ordning de lagras pÄ disk sorterade efter indexnyckeln. En clustering-faktor som ligger nÀra antalet rader indikerar att raderna Àr slumpmÀssigt spridda över databaskluster i förhÄllande till indexnyckeln. Om databasen gör en full tabellscanning hÀmtar databasen inte rader i nÄgon sorterad ordning efter denna indexnyckel.

I detta fall Àr data perfekt sorterade, sÄ clustering-faktorn kommer att vara lika med eller nÀra antalet upptagna block i tabellen. För en standard blockstorlek pÄ 8 kilobyte kan man förvÀnta sig att ett block rymmer cirka tusen smala nummervÀrden, sÄ antalet block, och dÀrmed clustering-faktorn, kommer att vara cirka tiotal.

Vid vilka vÀrden av N kommer följande skript att köras framgÄngsrikt i en vanlig databas med standardinstÀllningar?

create table t (
    a varchar2(N char),
    b varchar2(N char),
    c varchar2(N char),
    d varchar2(N char));
 
create index t_i on t (a, b, c, d);

  • 100
  • 200
  • 400
  • 800
  • 1600
  • 3200
  • 6400

SvarEnligt Oracle-dokumentationen (citerad frÄn 11.2):

Logiska datab grÀnser

Objekt
Typ av begrÀnsning
BegrÀnsningsvÀrde

Index
Total storlek av indexerat kolumn
75% av databasklusterstorleken minus viss overhead

SÄledes fÄr den totala storleken pÄ de indexerade kolumnerna inte överstiga 6 KB. Vad som hÀnder dÀrfter beror pÄ den valda databaskodningen. För kodningen AL32UTF8 kan en symbol ta upp till 4 byte, vilket innebÀr att cirka 1500 symboler kan fÄ plats i 6 kilobyte i det vÀrsta fallet. DÀrför kommer Oracle att förbjuda skapandet av ett index vid N = 400 (nÀr nyckellÀngden i vÀrsta fall kommer att vara 1600 symboler * 4 byte + lÀngden av rowid), medan vid N = 200 (och mindre) kan skapandet av indexet utföras utan problem.

INSERT-operatören med APPEND-hint Àr avsedd för att ladda data i direktlÀge. Vad hÀnder om den tillÀmpas pÄ en tabell som har en trigger?

  • Data kommer att laddas i direktlĂ€ge, triggern aktiveras som den ska
  • Data kommer att laddas i direktlĂ€ge, men triggern kommer inte att utföras
  • Data kommer att laddas i konventionellt lĂ€ge, triggern aktiveras som den ska
  • Data kommer att laddas i konventionellt lĂ€ge, men triggern kommer inte att utföras
  • Data kommer inte att laddas, ett fel kommer att registreras

SvarRent tekniskt Àr detta frÄga om logik. För att hitta rÀtt svar skulle jag föreslÄ följande resonemangsmodell:

  1. Infogning i direktlÀge utförs genom att direkt bilda datablokkar, utan att gÄ genom SQL-motorn, vilket möjliggör hög hastighet. DÀrför Àr det mycket svÄrt att sÀkerstÀlla att triggern utförs, om det ens Àr möjligt, och det finns ingen mening med det, eftersom det ÀndÄ kraftigt skulle bromsa infogningen.
  2. Att triggern inte utförs kommer att leda till att tillstÄndet hos databasen som helhet (andra tabeller) kommer att bero pÄ vilket lÀge dessa data har infogats. Detta skulle uppenbart underminera dataintegriteten och kan inte tillÀmpas som en lösning i produktion.
  3. OförmÄgan att utföra den begÀrda operationen betraktas generellt som ett fel. Men hÀr bör vi komma ihÄg att APPEND Àr en hint, och den allmÀnna logiken med hints Àr att de beaktas om det Àr möjligt; om inte, sÄ utförs operatören utan att ta hÀnsyn till hint.

SÄledes Àr det förvÀntade svaret - data kommer att laddas i normalt (SQL) lÀge, triggern aktiveras.

Enligt Oracle-dokumentationen (citerat frÄn 8.04):

ÖvertrĂ€delser av restriktionerna kommer att leda till att satsen körs sekventiellt, med den konventionella insĂ€ttningsvĂ€gen, utan varningar eller felmeddelanden. Ett undantag Ă€r restriktionen mot satser som kommer Ă„t samma tabell mer Ă€n en gĂ„ng i en transaktion, vilket kan orsaka felmeddelanden.
Till exempel, om det finns triggar eller referentiell integritet pÄ tabellen, kommer APPEND-hintet att ignoreras nÀr du försöker anvÀnda direktladdning INSERT (seriel eller parallell), liksom PARALLEL-hintet eller klausulen, om det finns nÄgot.

Vad hÀnder nÀr följande skript körs?

create table t(i integer not null primary key, j integer references t);
 
create trigger t_a_i after insert on t for each row
declare
    pragma autonomous_transaction;
begin
    insert into t values (:new.i + 1, :new.i);
    commit;
end;
/
 
insert into t values (1, null);

  • FramgĂ„ngsrik körning
  • Misslyckande pĂ„ grund av syntaxfel
  • Fel relaterat till otillĂ„ten autonom transaktion
  • Fel relaterat till överskridande av maximal anropsnivĂ„
  • Fel relaterat till en brytning av en utlĂ€ndsk nyckel
  • Fel relaterat till lĂ„sningar

SvarTabellen och triggarna skapas helt korrekt och denna operation bör inte orsaka problem. Autonoma transaktioner i triggar Àr ocksÄ tillÄtna, annars skulle det vara omöjligt, till exempel loggning.

Efter att den första raden infogats skulle den framgÄngsrika triggen leda till en andra infogning, vilket skulle orsaka att triggen kördes igen, infoga en tredje rad och sÄ vidare tills kommandot misslyckade pÄ grund av överskridande av maximal anropsnivÄ. Emellertid intrÀffar en annan subtil punkt. Vid körning av triggen för den första infogade posten har commit Ànnu inte utförts. DÀrför försöker triggen, som arbetar i en autonom transaktion, att infoga en rad i tabellen som refererar till en Ànnu icke-committad post. Detta leder till vÀntan (den autonoma transaktionen vÀntar pÄ commit av huvudet för att förstÄ om data kan infogas) och samtidigt vÀntar den huvudsakliga transaktionen pÄ commit av den autonoma för att fortsÀtta arbetet efter triggen. Det uppstÄr en deadlock och som en följd av detta avbryts den autonoma transaktionen pÄ grund av lÄsningar.

Endast registrerade anvÀndare kan delta i omröstningen. Logga in, tack.

Var det svÄrt?

  • Som tvĂ„ fingrar, löste allt rĂ€tt med en gĂ„ng.

  • Inte sĂ€rskilt, jag gjorde fel pĂ„ ett par frĂ„gor.

  • Jag löste hĂ€lften rĂ€tt.

  • Jag gissade svaret tvĂ„ gĂ„nger!

  • Jag skriver i kommentarerna

14 anvÀndare röstade. 10 anvÀndare avstod.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster