Prateći stope Highload++ Siberia 2019 - 8 zadataka na Oracle-u

Zdravo!

Od 24. do 25. juna u Novosibirsku je održana konferencija Highload++ Siberia 2019. Bili su tamo i naši momci izvještaj “Oracle kontejnerske baze podataka (CDB/PDB) i njihova praktična upotreba za razvoj softvera”, objavit ćemo tekstualnu verziju nešto kasnije. Bilo je super, hvala olegbunin za organizaciju, kao i za sve koji su došli.

Prateći stope Highload++ Siberia 2019 - 8 zadataka na Oracle-u
U ovom postu želimo sa vama podijeliti probleme koje smo imali na našem štandu kako biste mogli testirati svoje znanje o Oracleu. Ispod reza nalazi se 8 zadataka, opcije odgovora i objašnjenja.

Koja je maksimalna vrijednost sekvence koju ćemo vidjeti kao rezultat izvršavanja sljedeće skripte?

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
  • Ne, doći će do greške

OdgovoriPrema Oracle dokumentaciji (citirano od 8.1.6):
Unutar jednog SQL izraza, Oracle će povećati sekvencu samo jednom po redu. Ako izraz sadrži više od jedne reference na NEXTVAL za sekvencu, Oracle povećava sekvencu jednom i vraća istu vrijednost za sva pojavljivanja NEXTVAL. Ako izraz sadrži reference i na CURRVAL i na NEXTVAL, Oracle povećava sekvencu i vraća istu vrijednost za CURRVAL i NEXTVAL bez obzira na njihov redoslijed unutar izraza.

Prema tome, maksimalna vrijednost će odgovarati broju redova, odnosno 5.

Koliko će redova biti u tabeli kao rezultat pokretanja sljedeće skripte?

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

OdgovoriPrema Oracle dokumentaciji (citirano od 11.2):

Prije izvršavanja bilo koje SQL naredbe, Oracle označava implicitnu točku spremanja (nije dostupna vama). Zatim, ako izraz ne uspije, Oracle ga automatski vraća nazad i vraća primjenjivi kod greške u SQLCODE u SQLCA. Na primjer, ako INSERT izraz uzrokuje grešku pokušavajući umetnuti duplikat vrijednosti u jedinstveni indeks, izraz se vraća nazad.

Pozivanje HP-a od klijenta se takođe smatra i obrađuje kao jedna izjava. Dakle, prvi HP poziv se uspešno završava, nakon što su umetnuta tri zapisa; drugi HP poziv se završava greškom i vraća četvrti zapis koji je uspeo da ubaci; treći poziv ne uspijeva, i postoje tri zapisa u tabeli.

Koliko će redova biti u tabeli kao rezultat pokretanja sljedeće skripte?

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

OdgovoriPrema Oracle dokumentaciji (citirano od 11.2):

Ograničenje provjere vam omogućava da specificirate uslov koji svaki red u tabeli mora zadovoljiti. Da bi se zadovoljilo ograničenje, svaki red u tabeli mora učiniti uslov ili TRUE ili nepoznat (zbog nule). Kada Oracle procijeni uvjet ograničenja provjere za određeni red, bilo koji naziv stupaca u uvjetu odnosi se na vrijednosti stupaca u tom redu.

Dakle, vrijednost null će proći provjeru, a anonimni blok će se uspješno izvršiti do pokušaja umetanja vrijednosti 3. Nakon toga, blok za obradu grešaka će obrisati izuzetak, neće doći do vraćanja i u tabeli će ostati četiri reda sa vrijednostima 1, null, 2 i opet null.

Koji parovi vrijednosti će zauzeti istu količinu prostora u bloku?

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', 'Вася', 10, 10, 'Д', 'Вася');

  • A i X
  • B i Y
  • C i K
  • C i Z
  • K i Z
  • Ja i J
  • J i X
  • Sve navedeno

OdgovoriEvo izvoda iz dokumentacije (12.1.0.2) o skladištenju različitih tipova podataka u Oracle-u.

CHAR Tip podataka
Tip podataka CHAR specificira niz znakova fiksne dužine u skupu znakova baze podataka. Navodite skup znakova baze podataka kada kreirate svoju bazu podataka. Oracle osigurava da sve vrijednosti pohranjene u stupcu CHAR imaju dužinu specificiranu veličinom u semantici odabrane dužine. Ako umetnete vrijednost koja je kraća od dužine stupca, onda Oracle prazni vrijednost u dužinu stupca.

VARCHAR2 Tip podataka
VARCHAR2 tip podataka specificira niz znakova varijabilne dužine u skupu znakova baze podataka. Navodite skup znakova baze podataka kada kreirate svoju bazu podataka. Oracle pohranjuje vrijednost znakova u kolonu VARCHAR2 točno onako kako je vi navedete, bez ikakvih praznih polja, pod uvjetom da vrijednost ne prelazi dužinu kolone.

NUMBER vrsta podataka
Tip podataka NUMBER pohranjuje nulu, kao i pozitivne i negativne fiksne brojeve sa apsolutnim vrijednostima od 1.0 x 10-130 do, ali ne uključujući 1.0 x 10126. Ako navedete aritmetički izraz čija vrijednost ima apsolutnu vrijednost veću ili jednaku 1.0 x 10126, onda Oracle vraća grešku. Svaka vrijednost NUMBER zahtijeva od 1 do 22 bajta. Uzimajući ovo u obzir, veličina stupca u bajtovima za određenu numeričku vrijednost podataka BROJ(p), gdje je p preciznost date vrijednosti, može se izračunati pomoću sljedeće formule: ROUND((dužina(p)+s)/2))+1 gdje je s jednaka nuli ako je broj pozitivan, a s jednak 1 ako je broj negativan.

Osim toga, uzmimo izvod iz dokumentacije o pohranjivanju nul vrijednosti.

Null je odsustvo vrijednosti u koloni. Null označava podatke koji nedostaju, nepoznati ili neprimjenjivi. Null se pohranjuje u bazi podataka ako padaju između stupaca s vrijednostima podataka. U ovim slučajevima im je potreban 1 bajt za pohranjivanje dužine kolone (nula). Završne nule u redu ne zahtijevaju pohranu jer novo zaglavlje reda signalizira da su preostale kolone u prethodnom redu nule. Na primjer, ako su posljednje tri kolone u tablici null, tada se za te stupce ne pohranjuju podaci.

Na osnovu ovih podataka gradimo rezonovanje. Pretpostavljamo da baza podataka koristi AL32UTF8 kodiranje. U ovom kodiranju ruska slova će zauzimati 2 bajta.

1) A i X, vrijednost polja a 'Y' zauzima 1 bajt, vrijednost polja x 'D' zauzima 2 bajta
2) B i Y, 'Vasya' u b vrijednost će biti dopunjena razmacima do 10 znakova i zauzet će 14 bajtova, 'Vasya' u d će zauzeti 8 bajtova.
3) C i K. Oba polja imaju vrijednost NULL, iza njih su značajna polja, tako da zauzimaju 1 bajt.
4) C i Z. Oba polja imaju vrijednost NULL, ali polje Z je posljednje u tabeli, tako da ne zauzima prostor (0 bajtova). Polje C zauzima 1 bajt.
5) K i Z. Slično kao u prethodnom slučaju. Vrijednost u polju K zauzima 1 bajt, u Z – 0.
6) I i J. Prema dokumentaciji, obje vrijednosti će zauzeti 2 bajta. Dužinu izračunavamo koristeći formulu preuzetu iz dokumentacije: round( (1 + 0)/2) +1 = 1 + 1 = 2.
7) J i X. Vrijednost u polju J će zauzeti 2 bajta, vrijednost u polju X će zauzeti 2 bajta.

Ukupno, ispravne opcije su: C i K, I i J, J i X.

Koliki će otprilike biti faktor grupisanja T_I indeksa?

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

  • Oko desetina
  • O stotinama
  • Oko hiljada
  • Oko desetina hiljada

OdgovoriPrema Oracle dokumentaciji (citirano od 12.1):

Za indeks B-stabla, faktor grupisanja indeksa mjeri fizičko grupisanje redova u odnosu na vrijednost indeksa.

Faktor grupiranja indeksa pomaže optimizatoru da odluči da li je skeniranje indeksa ili skeniranje pune tabele efikasnije za određene upite). Nizak faktor grupisanja ukazuje na efikasno skeniranje indeksa.

Faktor grupisanja koji je blizak broju blokova u tabeli ukazuje na to da su redovi fizički poredani u blokovima tabele pomoću indeksnog ključa. Ako baza podataka izvrši potpuno skeniranje tablice, tada baza podataka teži da dohvati redove kako su pohranjeni na disku sortirani po indeksnom ključu. Faktor grupisanja koji je blizak broju redova ukazuje na to da su redovi nasumično raspoređeni po blokovima baze podataka u odnosu na indeksni ključ. Ako baza podataka izvrši potpuno skeniranje tablice, tada baza podataka neće dohvaćati redove u bilo kojem sortiranom redoslijedu prema ovom ključu indeksa.

U ovom slučaju, podaci su idealno sortirani, tako da će faktor grupisanja biti jednak ili blizak broju zauzetih blokova u tabeli. Za standardnu ​​veličinu bloka od 8 kilobajta, možete očekivati ​​da će oko hiljadu vrijednosti uskih brojeva stati u jedan blok, tako da će broj blokova, a kao rezultat, faktor grupisanja biti oko desetina.

Pri kojim vrijednostima N će se sljedeća skripta uspješno izvršiti u redovnoj bazi podataka sa standardnim postavkama?

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

OdgovoriPrema Oracle dokumentaciji (citirano od 11.2):

Ograničenja logičke baze podataka

stavka
Vrsta ograničenja
Limit Value

indeksi
Ukupna veličina indeksirane kolone
75% veličine bloka baze podataka minus neki dodatni troškovi

Dakle, ukupna veličina indeksiranih kolona ne bi trebala prelaziti 6Kb. Šta će se dalje dogoditi ovisi o odabranom osnovnom kodiranju. Za AL32UTF8 kodiranje, jedan znak može zauzeti najviše 4 bajta, tako da će u najgorem slučaju oko 6 karaktera stati u 1500 kilobajta. Prema tome, Oracle će zabraniti kreiranje indeksa na N = 400 (kada je dužina ključa u najgorem slučaju 1600 znakova * 4 bajta + dužina niza), dok na N = 200 (ili manje) kreiranje indeksa će raditi bez problema.

Operator INSERT sa nagovještajem APPEND dizajniran je za učitavanje podataka u direktnom načinu rada. Šta se dešava ako se primeni na sto na kome visi okidač?

  • Podaci će biti učitani u direktnom načinu rada, okidač će raditi kako se očekuje
  • Podaci će biti učitani u direktnom načinu rada, ali se okidač neće izvršiti
  • Podaci će se učitavati u konvencionalnom načinu rada, okidač će raditi kako treba
  • Podaci će biti učitani u konvencionalnom načinu rada, ali okidač neće biti izvršen
  • Podaci se neće učitati, bit će zabilježena greška

OdgovoriU suštini, ovo je više pitanje logike. Da biste pronašli tačan odgovor, predložio bih sljedeći model rezonovanja:

  1. Umetanje u direktnom modu se vrši direktnim formiranjem bloka podataka, zaobilazeći SQL mašinu, što osigurava veliku brzinu. Stoga je osiguranje izvršavanja okidača vrlo teško, ako ne i nemoguće, i nema smisla u tome, jer će i dalje radikalno usporiti umetanje.
  2. Neizvršenje okidača će dovesti do činjenice da će, ako su podaci u tabeli isti, stanje baze podataka u cjelini (ostale tabele) ovisiti o načinu u kojem su ti podaci umetnuti. Ovo će očito uništiti integritet podataka i ne može se primijeniti kao rješenje u proizvodnji.
  3. Nemogućnost izvođenja tražene operacije se općenito tretira kao greška. Ali ovdje treba imati na umu da je APPEND hint, a opća logika nagoveštaja je da se oni uzimaju u obzir ako je moguće, ali ako ne, operator se izvršava bez uzimanja nagoveštaja u obzir.

Dakle, očekivani odgovor je podaci će se učitati u normalnom (SQL) načinu rada, okidač će se aktivirati.

Prema Oracle dokumentaciji (citirano od 8.04):

Kršenja ograničenja će uzrokovati da se izraz izvršava serijski, koristeći konvencionalnu stazu umetanja, bez upozorenja ili poruka o grešci. Izuzetak je ograničenje da izrazi pristupaju istoj tablici više puta u transakciji, što može uzrokovati poruke o grešci.
Na primjer, ako su okidači ili referentni integritet prisutni u tablici, tada će nagoveštaj APPEND biti zanemaren kada pokušate koristiti INSERT s direktnim učitavanjem (serijski ili paralelni), kao i PARALLEL hint ili klauzula, ako ih ima.

Šta će se dogoditi kada se izvrši sljedeća skripta?

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);

  • Uspješan završetak
  • Greška zbog sintaksičke greške
  • Greška: autonomna transakcija nije važeća
  • Greška u vezi sa prekoračenjem maksimalnog ugniježđenja poziva
  • Greška kršenja stranog ključa
  • Greška u vezi sa bravama

OdgovoriTablica i okidač su kreirani sasvim korektno i ova operacija ne bi trebala dovesti do problema. Autonomne transakcije u okidaču su također dozvoljene, inače evidentiranje ne bi bilo moguće, na primjer.

Nakon umetanja prvog reda, uspješno aktiviranje okidača uzrokovalo bi umetanje drugog reda, uzrokujući ponovno aktiviranje okidača, umetanje trećeg reda i tako dalje sve dok izraz nije uspio zbog prekoračenja maksimalnog ugniježđenja poziva. Međutim, još jedna suptilna tačka dolazi u obzir. U vrijeme kada se okidač izvršava, urezivanje još nije završeno za prvi umetnuti zapis. Stoga, okidač koji se izvodi u autonomnoj transakciji pokušava umetnuti u tablicu red koji upućuje na strani ključ na zapis koji još nije urezan. Ovo rezultira čekanjem (autonomna transakcija čeka da se glavna transakcija izvrši da vidi može li umetnuti podatke) i u isto vrijeme glavna transakcija čeka da autonomna transakcija nastavi s radom nakon okidača. Dolazi do zastoja i, kao rezultat toga, autonomna transakcija se otkazuje zbog razloga vezanih za zaključavanje.

Samo registrovani korisnici mogu učestvovati u anketi. Prijavite semolim.

Bilo je teško?

  • Kao dva prsta, odmah sam sve ispravno odlučio.

  • Ne baš, pogriješio sam u nekoliko pitanja.

  • Polovinu sam riješio tačno.

  • Dvaput sam pogodio odgovor!

  • Pisaću u komentarima

Glasalo je 14 korisnika. Uzdržano je bilo 10 korisnika.

izvor: www.habr.com

Dodajte komentar