Sekvante la paŝojn de Highload++ Siberio 2019 - 8 taskoj en Oracle

Saluton!

La 24-25-an de junio okazis en Novosibirsk la konferenco Highload++ Siberia 2019. Ankaŭ niaj infanoj estis tie raporto "Orakolaj ujdatumbazoj (CDB/PDB) kaj ilia praktika uzo por programaro", ni publikigos tekstan version iom poste. Ĝi estis mojosa, dankon olegbunin por la organizo, same kiel al ĉiuj, kiuj venis.

Sekvante la paŝojn de Highload++ Siberio 2019 - 8 taskoj en Oracle
En ĉi tiu afiŝo, ni ŝatus dividi kun vi la problemojn, kiujn ni havis ĉe nia budo, por ke vi povu testi vian Oracle-scion. Sub la tranĉo estas 8 problemoj, respondelektoj kaj klarigo.

Kio estas la maksimuma sinsekva valoro, kiun ni vidos rezulte de ekzekuto de la sekva skripto?

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, estos eraro

ResponduLaŭ Oracle-dokumentado (citita el 8.1.6):
Ene de ununura SQL-deklaro, Oracle pliigos la sekvencon nur unufoje por vico. Se deklaro enhavas pli ol unu referencon al NEXTVAL por sekvenco, Oracle pliigas la sekvencon unufoje kaj resendas la saman valoron por ĉiuj okazoj de NEXTVAL. Se deklaro enhavas referencojn al kaj CURRVAL kaj NEXTVAL, Oracle pliigas la sekvencon kaj resendas la saman valoron por kaj CURRVAL kaj NEXTVAL sendepende de ilia ordo ene de la deklaro.

Tiel, la maksimuma valoro respondas al la nombro da linioj, tio estas 5.

Kiom da vicoj estos en la tabelo kiel rezulto de rulado de la sekva skripto?

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

ResponduLaŭ Oracle-dokumentado (citita el 11.2):

Antaŭ ol ekzekuti iun ajn SQL-deklaron, Oracle markas implican konservpunkton (ne havebla al vi). Tiam, se la deklaro malsukcesas, Oracle ruliĝas ĝin aŭtomate kaj resendas la aplikeblan erarkodon al SQLCODE en la SQLCA. Ekzemple, se INSERT deklaro kaŭzas eraron provante enigi duplikatan valoron en unika indekso, la deklaro estas rerulita.

Voki HP de la kliento ankaŭ estas konsiderata kaj procesita kiel ununura deklaro. Tiel, la unua HP-voko finiĝas sukcese, enmetinte tri rekordojn; la dua HP-voko finiĝas per eraro kaj retroiras la kvaran rekordon, kiun ĝi sukcesis enmeti; la tria voko malsukcesas, kaj estas tri rekordoj en la tabelo.

Kiom da vicoj estos en la tabelo kiel rezulto de rulado de la sekva skripto?

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

ResponduLaŭ Oracle-dokumentado (citita el 11.2):

Kontrola limo ebligas al vi specifi kondiĉon, kiun ĉiu vico en la tabelo devas plenumi. Por kontentigi la limon, ĉiu vico en la tabelo devas fari la kondiĉon aŭ VERA aŭ nekonata (pro nulo). Kiam Oracle taksas kontrolan limkondiĉon por aparta vico, ĉiuj kolumnomoj en la kondiĉo rilatas al la kolumnaj valoroj en tiu vico.

Tiel, la valoro nulo preterpasos la kontrolon, kaj la anonima bloko estos ekzekutita sukcese ĝis provo enigi la valoron 3. Post ĉi tio, la erartrakta bloko malplenigos la escepton, neniu retroiro okazos, kaj restos kvar vicoj en la tabelo kun valoroj 1, nulo, 2 kaj nulo denove.

Kiuj paroj da valoroj okupos la saman spacon en la bloko?

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 kaj X
  • B kaj Y
  • C kaj K
  • C kaj Z
  • K kaj Z
  • mi kaj J
  • J kaj X
  • Ĉiuj listigitaj

ResponduJen eltiraĵoj el la dokumentado (12.1.0.2) pri konservado de diversaj specoj de datumoj en Oracle.

Tipo de datumoj CHAR
La CHAR-datumtipo specifas fikslongan signaron en la datumbaza signoaro. Vi specifas la datumbazan signaron kiam vi kreas vian datumbazon. Orakolo certigas, ke ĉiuj valoroj stokitaj en CHAR-kolumno havas la longon specifitan laŭ grandeco en la elektita longeca semantiko. Se vi enmetas valoron kiu estas pli mallonga ol la kolumlongo, tiam Oracle malplenigas la valoron al kolumlongo.

Tipo de datumoj VARCHAR2
La datumtipo VARCHAR2 specifas variablo-longan signaron en la datumbaza signoaro. Vi specifas la datumbazan signaron kiam vi kreas vian datumbazon. Oracle konservas signan valoron en VARCHAR2-kolumno ekzakte kiel vi specifas ĝin, sen ia malplena kompletigo, kondiĉe ke la valoro ne superas la longon de la kolumno.

NUMBER-Datumtipo
La datumtipo de NUMERO konservas nulon kaj ankaŭ pozitivajn kaj negativajn fiksajn nombrojn kun absolutaj valoroj de 1.0 x 10-130 ĝis sed ne inkluzive de 1.0 x 10126. Se vi specifigas aritmetikan esprimon, kies valoro havas absolutan valoron pli granda ol aŭ egala al 1.0 x 10126, tiam Oracle resendas eraron. Ĉiu NUMERO-valoro postulas de 1 ĝis 22 bajtoj. Konsiderante tion, la kolumngrandeco en bajtoj por speciala nombra datenvaloro NUMERO(p), kie p estas la precizeco de antaŭfiksita valoro, povas esti kalkulita uzante la sekvan formulon: RONDA ((longo (p)+s)/2))+1 kie s egalas nul se la nombro estas pozitiva, kaj s egalas al 1 se la nombro estas negativa.

Krome, ni prenu eltiraĵon el la dokumentaro pri stokado de Nulaj valoroj.

Nulo estas la foresto de valoro en kolumno. Nuloj indikas mankantajn, nekonatajn aŭ neuzeblajn datumojn. Nuloj estas stokitaj en la datumbazo se ili falas inter kolumnoj kun datenvaloroj. En ĉi tiuj kazoj, ili postulas 1 bajton por stoki la longon de la kolumno (nul). Malantaŭaj nuloj en vico postulas neniun stokadon ĉar nova vica kaplinio signalas, ke la ceteraj kolumnoj en la antaŭa vico estas nulaj. Ekzemple, se la lastaj tri kolumnoj de tabelo estas nulaj, tiam neniuj datumoj estas stokitaj por ĉi tiuj kolumnoj.

Surbaze de ĉi tiuj datumoj, ni konstruas rezonadon. Ni supozas, ke la datumbazo uzas AL32UTF8-kodigon. En ĉi tiu kodado, rusaj literoj okupos 2 bajtojn.

1) A kaj X, la valoro de kampo a 'Y' prenas 1 bajton, la valoro de kampo x 'D' prenas 2 bajtojn
2) B kaj Y, 'Vasya' en b la valoro estos plenigita per spacoj ĝis 10 signoj kaj prenos 14 bajtojn, 'Vasya' en d prenos 8 bajtojn.
3) C kaj K. Ambaŭ kampoj havas la valoron NULL, post ili estas signifaj kampoj, do ili okupas 1 bajton.
4) C kaj Z. Ambaŭ kampoj havas la valoron NULL, sed kampo Z estas la lasta en la tabelo, do ĝi ne okupas spacon (0 bajtoj). Kampo C okupas 1 bajton.
5) K kaj Z. Simile al la antaŭa kazo. La valoro en la kampo K okupas 1 bajton, en Z – 0.
6) I kaj J. Laŭ la dokumentado, ambaŭ valoroj prenos 2 bajtojn. Ni kalkulas la longon per la formulo prenita el la dokumentaro: round( (1 + 0)/2) +1 = 1 + 1 = 2.
7) J kaj X. La valoro en la kampo J prenos 2 bajtojn, la valoro en la kampo X prenos 2 bajtojn.

Entute, la ĝustaj opcioj estas: C kaj K, I kaj J, J kaj X.

Kio proksimume estos la grupiga faktoro de la T_I-indekso?

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

  • Ĉirkaŭ dekoj
  • Ĉirkaŭ centoj
  • Pri miloj
  • Ĉirkaŭ dekoj da miloj

ResponduLaŭ Oracle-dokumentado (citita el 12.1):

Por B-arba indekso, la indeksa grupiga faktoro mezuras la fizikan grupigon de vicoj rilate al indeksa valoro.

La indeksa grupiga faktoro helpas la optimumiganton decidi ĉu indeksa skanado aŭ plena tabelskanado estas pli efika por certaj demandoj). Malalta grupiga faktoro indikas efikan indeksan skanadon.

Agrupiga faktoro kiu estas proksima al la nombro da blokoj en tabelo indikas ke la vicoj estas fizike ordigitaj en la tabelblokoj per la indeksa ŝlosilo. Se la datumbazo elfaras plenan tabelskanadon, tiam la datumbazo emas preni la vicojn kiam ili estas stokitaj sur disko ordigitaj per la indeksa ŝlosilo. Agrupiga faktoro kiu estas proksima al la nombro da vicoj indikas ke la vicoj estas disigitaj hazarde trans la datumbazblokoj rilate al la indeksa ŝlosilo. Se la datumbazo elfaras plenan tabelskanadon, tiam la datumbazo ne reakirus vicojn en ajna ordo per ĉi tiu indeksa ŝlosilo.

En ĉi tiu kazo, la datumoj estas ideale ordigitaj, do la grupiga faktoro estos egala aŭ proksima al la nombro da okupataj blokoj en la tabelo. Por norma blokgrandeco de 8 kilobajtoj, vi povas atendi, ke ĉirkaŭ mil mallarĝaj nombrovaloroj konvenos en unu blokon, do la nombro da blokoj, kaj kiel rezulto, la grupiga faktoro estos proksimume dekoj.

Je kiaj valoroj de N la sekva skripto estos ekzekutita sukcese en regula datumbazo kun normaj agordoj?

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

ResponduLaŭ Oracle-dokumentado (citita el 11.2):

Limoj de Logika Datumaro

objekton
Tipo de Limo
Limvaloro

indeksoj
Suma grandeco de indeksita kolumno
75% de la datumbaza blokgrandeco minus iom da supra kosto

Tiel, la totala grandeco de indeksitaj kolumnoj ne devus superi 6Kb. Kio okazas poste dependas de la elektita baza kodado. Por AL32UTF8-kodigo, unu signo povas okupi maksimume 4 bajtojn, do en la plej malbona kazo, ĉirkaŭ 6 signoj konvenos en 1500 kilobajtoj. Tial, Oracle malpermesos kreadon de indeksoj je N = 400 (kiam la plej malbona kazo ŝlosillongo estas 1600 signoj * 4 bajtoj + longa longo), dum ĉe N = 200 (aŭ malpli) krei la indekson funkcios sen problemoj.

La INSERT-funkciigisto kun la APPEND sugesto estas dizajnita por ŝarĝi datumojn en rekta reĝimo. Kio okazas se ĝi estas aplikata al la tablo, sur kiu pendas la ellasilo?

  • La datumoj estos ŝarĝitaj en rekta reĝimo, la ellasilo funkcios kiel atendite
  • La datumoj estos ŝarĝitaj en rekta reĝimo, sed la ellasilo ne estos ekzekutita
  • La datumoj estos ŝarĝitaj en konvencia reĝimo, la ellasilo funkcios kiel ĝi devus
  • La datumoj estos ŝarĝitaj en konvencia reĝimo, sed la ellasilo ne estos ekzekutita
  • La datumoj ne estos ŝarĝitaj, eraro estos registrita

ResponduEsence, ĉi tio estas pli ol demando de logiko. Por trovi la ĝustan respondon, mi sugestus la jenan rezonan modelon:

  1. Enmeto en rekta reĝimo estas farita per rekta formado de datumbloko, preterirante la SQL-motoron, kiu certigas altan rapidon. Tiel, certigi la ekzekuton de la ellasilo estas tre malfacila, se ne neebla, kaj ĉi tio ne havas signifon, ĉar ĝi ankoraŭ radikale malrapidigos la enmeton.
  2. Malsukceso efektivigi la ellasilon kondukos al la fakto, ke, se la datumoj en la tabelo estas la sama, la stato de la datumbazo entute (aliaj tabeloj) dependos de la reĝimo, en kiu ĉi tiuj datumoj estis enmetitaj. Ĉi tio evidente detruos datuman integrecon kaj ne povas esti aplikata kiel solvo en produktado.
  3. La malkapablo plenumi la petitan operacion estas ĝenerale traktata kiel eraro. Sed ĉi tie ni memoru, ke APPEND estas sugesto, kaj la ĝenerala logiko de sugestoj estas, ke ili estas konsiderataj se eble, sed se ne, la operatoro estas ekzekutita sen konsideri la sugeston.

Do la atendata respondo estas la datumoj estos ŝarĝitaj en normala (SQL) reĝimo, la ellasilo pafos.

Laŭ Oracle-dokumentado (citita el 8.04):

Malobservoj de la restriktoj igos la deklaron ekzekuti serie, uzante la konvencian enigvojon, sen avertoj aŭ erarmesaĝoj. Escepto estas la limigo pri deklaroj alirantaj la saman tabelon pli ol unufoje en transakcio, kio povas kaŭzi erarmesaĝojn.
Ekzemple, se ellasiloj aŭ referenca integreco ĉeestas sur la tablo, tiam la APPEND-sugesto estos ignorita kiam vi provos uzi rekta-ŝarĝan INSERT (seriala aŭ paralela), same kiel la PARALLEL-sugesto aŭ klaŭzo, se ekzistas.

Kio okazos kiam la sekva skripto estos ekzekutita?

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

  • Sukcesa kompletigo
  • Fiasko pro sintaksa eraro
  • Eraro: Aŭtonoma Transakcio Ne Validas
  • Eraro rilata al superado de la maksimuma voka nestado
  • Eraro pri Malobservo de Fremda Ŝlosilo
  • Eraro rilata al seruroj

ResponduLa tablo kaj ellasilo estas kreitaj sufiĉe ĝuste kaj ĉi tiu operacio ne devus konduki al problemoj. Aŭtonomaj transakcioj en ellasilo ankaŭ estas permesitaj, alie protokolado ne eblus, ekzemple.

Post enmetado de la unua vico, sukcesa ellasilpafado kaŭzus la duan vicon esti enigita, kaŭzante la ellasilon pafi denove, enigante trian vicon, kaj tiel plu ĝis la deklaro malsukcesis pro superado de la maksimuma nestado de vokoj. Tamen, alia subtila punkto eniras en ludon. Kiam la ellasilo estas ekzekutita, kommit ankoraŭ ne estis kompletigita por la unua enigita rekordo. Sekve, ellasilo funkcianta en aŭtonoma transakcio provas enigi en la tabelon vicon kiu referencas fremdan ŝlosilon al rekordo kiu ankoraŭ ne estis farita. Ĉi tio rezultigas atendon (la aŭtonoma transakcio atendas ke la ĉefa transakcio kompromitas por vidi ĉu ĝi povas enmeti datumojn) kaj samtempe la ĉefa transakcio atendas, ke la aŭtonoma transakcio daŭre funkcias post la ellasilo. Blokiĝo okazas kaj, kiel rezulto, la aŭtonoma transakcio estas nuligita pro kialoj ligitaj al seruroj..

Nur registritaj uzantoj povas partopreni la enketon. Ensaluti, bonvolu.

Estis malfacile?

  • Kiel du fingroj, mi tuj decidis ĉion ĝuste.

  • Ne vere, mi eraris pri kelkaj demandoj.

  • Mi korekte solvis duonon de ĝi.

  • Mi divenis la respondon dufoje!

  • Mi skribos en la komentoj

14 uzantoj voĉdonis. 10 uzantoj sindetenis.

fonto: www.habr.com

Aldoni komenton