Follegt am Spass vum Highload++ Siberia 2019 - 8 Aufgaben op Oracle

Hallo!

De 24.-25. Juni war zu Novosibirsk d'Highload++ Siberia 2019 Konferenz ofgehalen. Eis Kärelen waren och do mellen "Oracle Container Datenbanken (CDB / PDB) an hir praktesch Notzung fir Software Entwécklung", mir wäerten eng Text Versioun e bësse méi spéit Post. Et war cool, merci olegbunin fir d'Organisatioun, wéi och fir jiddereen deen komm ass.

Follegt am Spass vum Highload++ Siberia 2019 - 8 Aufgaben op Oracle
An dësem Post wëlle mir mat Iech d'Problemer deelen, déi mir op eisem Stand haten, fir datt Dir Äert Oracle Wëssen testen kënnt. Ënnert dem Schnëtt sinn 8 Probleemer, Äntwertoptiounen an Erklärung.

Wat ass de maximale Sequenzwäert dee mir als Resultat vun der Ausféierung vum folgende Skript gesinn?

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
  • Nee, et gëtt e Feeler

ÄntwertNo Oracle Dokumentatioun (zitéiert vum 8.1.6):
Bannent enger eenzeger SQL Ausso wäert Oracle d'Sequenz nëmmen eemol pro Zeil erhéijen. Wann eng Ausso méi wéi eng Referenz op NEXTVAL fir eng Sequenz enthält, erhéicht Oracle d'Sequenz eemol a gëtt dee selwechte Wäert fir all Optriede vun NEXTVAL zréck. Wann eng Ausso Referenzen op béid CURRVAL an NEXTVAL enthält, erhéicht d'Oracle d'Sequenz a gëtt dee selwechte Wäert fir béid CURRVAL an NEXTVAL zréck onofhängeg vun hirer Uerdnung an der Ausso.

Sou, de maximale Wäert entsprécht der Unzuel vun de Linnen, dat ass 5.

Wéi vill Zeile wäerten an der Tabell sinn als Resultat vum folgenden Skript ze lafen?

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

ÄntwertNo Oracle Dokumentatioun (zitéiert vum 11.2):

Ier Dir eng SQL Ausso ausféiert, markéiert Oracle en impliziten Spuerpunkt (net fir Iech verfügbar). Dann, wann d'Ausso feelt, rullt d'Oracle se automatesch zréck a gëtt den applicabele Feelercode op SQLCODE an der SQLCA zréck. Zum Beispill, wann eng INSERT Ausso e Feeler verursaacht andeems Dir probéiert en Duplikatwäert an engem eenzegaartegen Index anzeginn, gëtt d'Ausso zréckgezunn.

Uruff HP vum Client gëtt och als eenzeg Ausso ugesinn a veraarbecht. Sou ass den éischten HP Uruff erfollegräich ofgeschloss, nodeems se dräi Rekorder agefouert hunn; den zweeten HP Uruff endet mat engem Feeler a rullt de véierte Rekord zréck, deen et fäerdeg bruecht huet ze setzen; den drëtten Uruff feelt, an et ginn dräi records an der Tabell.

Wéi vill Zeile wäerten an der Tabell sinn als Resultat vum folgenden Skript ze lafen?

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

ÄntwertNo Oracle Dokumentatioun (zitéiert vum 11.2):

Eng Scheckbeschränkung léisst Iech eng Konditioun spezifizéieren déi all Zeil an der Tabell muss erfëllen. Fir d'Begrenzung ze erfëllen, muss all Zeil an der Tabell d'Konditioun entweder TRUE oder onbekannt maachen (wéinst enger Null). Wann Oracle e Scheckbeschränkungsbedingung fir eng bestëmmte Zeil evaluéiert, bezéien all Kolonnennimm an der Bedingung op d'Kolonnwäerter an där Zeil.

Also passéiert de Wäert null de Scheck, an den anonyme Block gëtt erfollegräich ausgefouert bis e Versuch de Wäert 3 anzeginn. Duerno wäert de Feelerhandhabungsblock d'Ausnam läschen, kee Réckroll geschitt, an et gëtt véier Zeile lénks an der Tabell mat Wäerter 1, null, 2 an erëm null.

Wéi eng Paire vu Wäerter huelen déiselwecht Quantitéit u Plaz am Block op?

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 an X
  • B an Y
  • C an K
  • C an Z
  • K an Z
  • Ech an J
  • J an X
  • All opgezielt

ÄntwertHei sinn Auszich aus der Dokumentatioun (12.1.0.2) iwwer d'Späichere vun verschiddenen Zorte vun Daten am Oracle.

CHAR Datentyp
Den CHAR-Datentyp spezifizéiert e Charakterstring vun enger fixer Längt an der Datebank Zeechesaz. Dir spezifizéiert d'Datebank Zeechesaatz wann Dir Är Datebank erstellt. Oracle garantéiert datt all Wäerter, déi an enger CHAR Kolonn gespäichert sinn, d'Längt hunn, déi duerch d'Gréisst an der gewielter Längt Semantik spezifizéiert ass. Wann Dir e Wäert asetzt dee méi kuerz ass wéi d'Kolonnlängt, da setzt Oracle eidel de Wäert op d'Kolonnlängt.

VARCHAR2 Daten Typ
Den VARCHAR2-Datentyp spezifizéiert eng Variabel-Längt Zeechestring am Datebank Zeechesaz. Dir spezifizéiert d'Datebank Zeechesaatz wann Dir Är Datebank erstellt. Oracle späichert e Charakterwäert an enger VARCHAR2 Kolonn genau sou wéi Dir et spezifizéiert, ouni eidel Polsterung, virausgesat datt de Wäert net d'Längt vun der Kolonn iwwerschreift.

NUMMER Daten Typ
D'NUMMER Datentyp späichert Null souwéi positiv an negativ fix Zuelen mat absolute Wäerter vun 1.0 x 10-130 bis awer net abegraff 1.0 x 10126. 1.0 x 10126, da gëtt Oracle e Feeler zréck. All NUMMER Wäert erfuerdert vun 1 bis 22 Bytes. Wann Dir dëst berücksichtegt, kann d'Kolonngréisst a Bytes fir e bestëmmten numereschen Datewäert NUMBER (p), wou p d'Präzisioun vun engem bestëmmte Wäert ass, mat der folgender Formel berechent ginn: ROUND((Längt(p)+s)/2))+1 wou s gläich ass null wann d'Zuel positiv ass, an s gläich 1 wann d'Zuel negativ ass.

Zousätzlech, loosst eis en Extrait aus der Dokumentatioun iwwer d'Späichere vun Null Wäerter huelen.

En Null ass d'Feele vun engem Wäert an enger Kolonn. Nulls weisen fehlend, onbekannt oder inapplicabel Donnéeën. Nulls ginn an der Datebank gespäichert wa se tëscht Spalten mat Datewäerter falen. An dëse Fäll brauche se 1 Byte fir d'Längt vun der Kolonn (Null) ze späicheren. Trailing Nullen an enger Zeil erfuerderen keng Späichere well en neie Zeilheader signaliséiert datt déi verbleiwen Kolonnen an der viregter Zeil null sinn. Zum Beispill, wann déi lescht dräi Kolonnen vun enger Tabell null sinn, da gi keng Daten fir dës Kolonnen gespäichert.

Baséierend op dës Donnéeën bauen mir Begrënnung. Mir huelen un datt d'Datebank AL32UTF8 Kodéierung benotzt. An dëser Kodéierung wäerte russesch Buschtawen 2 Bytes besetzen.

1) A an X, de Wäert vum Feld a 'Y' hëlt 1 Byte, de Wäert vum Feld x 'D' hëlt 2 Bytes
2) B an Y, 'Vasya' an b de Wäert gëtt mat Plazen bis zu 10 Zeechen gepolstert an hëlt 14 Bytes, 'Vasya' an d hëlt 8 Bytes.
3) C an K. Béid Felder hunn de Wäert NULL, no hinnen ginn et bedeitend Felder, sou datt se 1 Byte besetzen.
4) C an Z. Béid Felder hunn de Wäert NULL, mee Feld Z ass déi lescht an der Tabell, sou datt et keng Plaz ophëlt (0 Bytes). Feld C besetzt 1 Byte.
5) K an Z. Ähnlech wéi de fréiere Fall. De Wäert am K Feld besetzt 1 Byte, an Z - 0.
6) I an J. Laut der Dokumentatioun huelen béid Wäerter 2 Bytes. Mir berechnen d'Längt mat der Formel aus der Dokumentatioun: Ronn ((1 + 0)/2) +1 = 1 + 1 = 2.
7) J an X. De Wäert am J-Feld hëlt 2 Bytes, de Wäert am X-Feld 2 Bytes.

Am Ganzen sinn déi richteg Optiounen: C an K, I an J, J an X.

Wat ongeféier wäert de Clusterfaktor vum T_I Index sinn?

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

  • Iwwer Zénger
  • Iwwer honnert
  • Iwwer dausende
  • Ongeféier Zéngdausende

ÄntwertNo Oracle Dokumentatioun (zitéiert vum 12.1):

Fir e B-Bam Index moosst den Indexclusterfaktor déi kierperlech Gruppéierung vu Reihen par rapport zu engem Indexwäert.

Den Indexclusterfaktor hëlleft dem Optimizer ze entscheeden ob en Index Scan oder voll Dësch Scan méi effizient ass fir verschidde Ufroen). En nidderegen Clusterfaktor weist en effizienten Indexscann un.

E Clusterfaktor deen no der Unzuel vun de Blocken an enger Tabell ass, weist datt d'Reihen kierperlech an den Tabelleblocken duerch den Indexschlëssel bestallt sinn. Wann d'Datebank e komplette Tabellescan ausféiert, da tendéiert d'Datebank d'Reihen ze recuperéieren wéi se op der Disk gespäichert sinn no dem Indexschlëssel zortéiert. E Clusterfaktor deen no der Unzuel vun de Reihen ass, weist datt d'Reihen zoufälleg iwwer d'Datebankblocken par rapport zum Indexschlëssel verspreet sinn. Wann d'Datebank e komplette Tabellescan ausféiert, da géif d'Datebank keng Reihen an enger zortéierter Uerdnung duerch dësen Indexschlëssel zréckzéien.

An dësem Fall sinn d'Donnéeën idealerweis zortéiert, sou datt de Clusterfaktor gläich oder no bei der Unzuel vun de besetzte Blocken an der Tabell ass. Fir eng Standardblockgréisst vun 8 Kilobytes kënnt Dir erwaarden datt ongeféier dausend schmuel Zuelwäerter an ee Block passen, sou datt d'Zuel vun de Blocken, an als Resultat, de Clusterfaktor wäert sinn iwwer Zénger.

A wéi enge Wäerter vun N gëtt de folgende Skript erfollegräich an enger regulärer Datebank mat Standardastellungen ausgefouert?

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

ÄntwertNo Oracle Dokumentatioun (zitéiert vum 11.2):

Logesch Datebank Limite

Kuurzmeldung
Zort Limit
Limitéiert Wäert

Indexen
Total Gréisst vun indexéiert Kolonn
75% vun der Datebankblockgréisst minus e puer Overhead

Also däerf d'Gesamtgréisst vun den indexéierte Sailen net méi wéi 6Kb sinn. Wat duerno geschitt hänkt vun der gewielter Basiskodéierung of. Fir AL32UTF8 Kodéierung kann ee Charakter maximal 4 Bytes besetzen, also am schlëmmste Fall passen 6 Kilobytes ongeféier 1500 Zeechen. Dofir wäert d'Oracle d'Indexkreatioun bei N = 400 net erlaben (wann déi schlëmmste Fall Schlëssellängt 1600 Zeechen * 4 Bytes + rowid Längt ass), wärend bei N = 200 (oder manner) den Index erstellen wäert ouni Probleemer schaffen.

Den INSERT Bedreiwer mam APPEND Hiweis ass entwéckelt fir Daten am direkte Modus ze lueden. Wat geschitt wann et op den Dësch applizéiert gëtt, op deem den Ausléiser hänkt?

  • D'Donnéeë ginn am direkte Modus gelueden, den Ausléiser funktionnéiert wéi erwaart
  • D'Donnéeë ginn am direkte Modus gelueden, awer den Ausléiser gëtt net ausgefouert
  • D'Donnéeë ginn am konventionelle Modus gelueden, den Ausléiser funktionnéiert wéi et soll
  • D'Donnéeë ginn am konventionelle Modus gelueden, awer den Ausléiser gëtt net ausgefouert
  • D'Donnéeë ginn net gelueden, e Feeler gëtt opgeholl

ÄntwertPrinzipiell ass dëst méi eng Fro vu Logik. Fir déi richteg Äntwert ze fannen, géif ech de folgende Begrënnungsmodell proposéieren:

  1. Insertion am direkten Modus gëtt duerch direkt Bildung vun engem Dateblock duerchgefouert, de SQL-Motor ëmgeet, wat eng héich Geschwindegkeet garantéiert. Also assuréieren d'Ausféierung vum Ausléiser ganz schwéier, wann net onméiglech, an et ass kee Sënn an dësem, well et wäert d'Insertioun nach radikal verlangsamen.
  2. Wann Dir den Ausléiser net ausféiert, féiert dat zu der Tatsaach datt wann d'Donnéeën an der Tabell d'selwecht sinn, den Zoustand vun der Datebank als Ganzt (aner Dëscher) hänkt vum Modus of an deem dës Donnéeën agefouert goufen. Dëst wäert selbstverständlech d'Datenintegritéit zerstéieren a kann net als Léisung an der Produktioun applizéiert ginn.
  3. D'Onméiglechkeet fir déi ugefrote Operatioun auszeféieren gëtt allgemeng als e Feeler behandelt. Awer hei sollte mir drun erënneren datt APPEND en Hiweis ass, an d'allgemeng Logik vun Hiweiser ass datt se berücksichtegt ginn wa méiglech, awer wann net, gëtt de Bedreiwer ausgefouert ouni den Hiweis ze berücksichtegen.

Also déi erwaart Äntwert ass d'Donnéeë ginn am normalen (SQL) Modus gelueden, den Ausléiser brennt.

No Oracle Dokumentatioun (zitéiert vum 8.04):

Violatioune vun de Restriktiounen féieren d'Erklärung seriell auszeféieren, mam konventionellen Insert Wee, ouni Warnungen oder Fehlermeldungen. Eng Ausnam ass d'Restriktioun op Aussoen, déi méi wéi eemol an enger Transaktioun op dee selwechten Dësch kommen, wat Fehlermeldungen verursaache kann.
Zum Beispill, wann Ausléiser oder referenzieller Integritéit um Dësch präsent sinn, da gëtt den APPEND Hiweis ignoréiert wann Dir probéiert direkt-Laascht INSERT (Serial oder Parallel) ze benotzen, souwéi de PARALLEL Hiweis oder Klausel, wann iwwerhaapt.

Wat geschitt wann de folgende Skript ausgefouert gëtt?

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

  • Erfollegräich Ofschloss
  • Feeler wéinst Syntaxfehler
  • Feeler: Autonom Transaktioun ass net gëlteg
  • Feeler am Zesummenhang mat der Iwwerschreiden vum maximalen Uruff Nesting
  • Auslännesch Schlëssel Violatioun Feeler
  • Feeler am Zesummenhang mat Spären

ÄntwertDen Dësch an den Ausléiser si ganz korrekt erstallt an dës Operatioun sollt net zu Probleemer féieren. Autonom Transaktiounen an engem Ausléiser sinn och erlaabt, soss wier d'Protokolléierung net méiglech, zum Beispill.

No der Aféierung vun der éischter Zeil, en erfollegräichen Ausléiserfeier géif d'zweet Zeil asetzen, wouduerch den Ausléiser erëm schéisst, eng drëtt Zeil asetzt, a sou weider bis d'Ausso gescheitert ass wéinst der Iwwerschreiden vum Maximum Nesting vun Uriff. Allerdéngs kënnt en anere subtile Punkt an d'Spill. Zu der Zäit wou den Ausléiser ausgefouert gëtt, ass d'Verpflichtung nach net ofgeschloss fir den éischten agebaute Rekord. Dofir probéiert en Ausléiser, deen an enger autonomer Transaktioun leeft, eng Zeil an den Dësch ze setzen, déi en auslännesche Schlëssel op e Rekord referéiert, deen nach net engagéiert gouf. Dëst resultéiert an enger Waarde (déi autonom Transaktioun waart op d'Haapttransaktioun fir sech ze verpflichte fir ze kucken ob et Daten aginn kann) a gläichzäiteg waart d'Haapttransaktioun op déi autonom Transaktioun fir weider no der Ausléiser ze schaffen. En Deadlock geschitt an als Resultat gëtt déi autonom Transaktioun annuléiert wéinst Grënn am Zesummenhang mat Spären.

Nëmme registréiert Benotzer kënnen un der Ëmfro deelhuelen. Umellen, wann ech glift.

Et war schwéier ze?

  • Wéi zwee Fanger hunn ech direkt alles richteg entscheet.

  • Net wierklech, ech war falsch op e puer Froen.

  • Ech hunn d'Halschent richteg geléist.

  • Ech hunn d'Äntwert zweemol geschat!

  • Ech schreiwen an de Kommentaren

14 Benotzer hunn gestëmmt. 10 Benotzer hu sech enthalen.

Source: will.com

Setzt e Commentaire