Sumusunod sa mga yapak ng Highload++ Siberia 2019 - 8 gawain sa Oracle

Привет!

Noong Hunyo 24-25, ginanap ang Highload++ Siberia 2019 conference sa Novosibirsk. Nandoon din ang mga kasama namin ulat "Mga database ng lalagyan ng Oracle (CDB/PDB) at ang kanilang praktikal na paggamit para sa pagbuo ng software", mag-publish kami ng isang bersyon ng teksto sa ibang pagkakataon. Ito ay cool, salamat olegbunin para sa organisasyon, gayundin sa lahat ng dumating.

Sumusunod sa mga yapak ng Highload++ Siberia 2019 - 8 gawain sa Oracle
Sa post na ito, nais naming ibahagi sa iyo ang mga problema na mayroon kami sa aming booth upang masubukan mo ang iyong kaalaman sa Oracle. Sa ibaba ng cut ay 8 mga problema, mga pagpipilian sa sagot at paliwanag.

Ano ang pinakamataas na halaga ng pagkakasunud-sunod na makikita natin bilang resulta ng pagpapatupad ng sumusunod na script?

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
  • Hindi, magkakaroon ng error

SagutinAyon sa dokumentasyon ng Oracle (sinipi mula sa 8.1.6):
Sa loob ng iisang SQL statement, ang Oracle ay dagdagan ang sequence nang isang beses lang bawat row. Kung ang isang statement ay naglalaman ng higit sa isang reference sa NEXTVAL para sa isang sequence, dinaragdagan ng Oracle ang sequence nang isang beses at ibinabalik ang parehong halaga para sa lahat ng paglitaw ng NEXTVAL. Kung ang isang pahayag ay naglalaman ng mga sanggunian sa parehong CURRVAL at NEXTVAL, dinaragdagan ng Oracle ang sequence at ibinabalik ang parehong halaga para sa parehong CURRVAL at NEXTVAL anuman ang kanilang pagkakasunud-sunod sa loob ng pahayag.

Kaya, ang ang maximum na halaga ay tumutugma sa bilang ng mga linya, iyon ay 5.

Ilang row ang nasa talahanayan bilang resulta ng pagpapatakbo ng sumusunod na script?

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

SagutinAyon sa dokumentasyon ng Oracle (sinipi mula sa 11.2):

Bago magsagawa ng anumang SQL statement, minarkahan ng Oracle ang isang implicit savepoint (hindi magagamit sa iyo). Pagkatapos, kung nabigo ang pahayag, awtomatikong ibabalik ito ng Oracle at ibabalik ang naaangkop na error code sa SQLCODE sa SQLCA. Halimbawa, kung ang isang INSERT na pahayag ay nagdudulot ng error sa pamamagitan ng pagsubok na magpasok ng isang duplicate na halaga sa isang natatanging index, ang pahayag ay ibabalik.

Ang pagtawag sa HP mula sa kliyente ay isinasaalang-alang din at pinoproseso bilang isang pahayag. Kaya, matagumpay na nakumpleto ang unang tawag sa HP, na naipasok ang tatlong tala; ang pangalawang tawag sa HP ay nagtatapos sa isang error at ibabalik ang ikaapat na tala na naipasok nito; nabigo ang ikatlong tawag, at mayroong tatlong tala sa talahanayan.

Ilang row ang nasa talahanayan bilang resulta ng pagpapatakbo ng sumusunod na script?

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

SagutinAyon sa dokumentasyon ng Oracle (sinipi mula sa 11.2):

Hinahayaan ka ng check constraint na tumukoy ng kundisyon na dapat matugunan ng bawat row sa talahanayan. Upang matugunan ang pagpilit, ang bawat hilera sa talahanayan ay dapat gawing TRUE o hindi alam ang kundisyon (dahil sa isang null). Kapag sinusuri ng Oracle ang isang kundisyon ng pagpilit sa pagsusuri para sa isang partikular na row, ang anumang mga pangalan ng column sa kundisyon ay tumutukoy sa mga value ng column sa row na iyon.

Kaya, ang value na null ay ipapasa sa tseke, at ang anonymous block ay matagumpay na maisasakatuparan hanggang sa isang pagtatangka na ipasok ang halaga 3. Pagkatapos nito, ang error sa paghawak ng block ay tatanggalin ang exception, walang rollback na magaganap, at magkakaroon ng apat na hanay na natitira sa talahanayan na may mga halaga 1, null, 2 at null muli.

Aling mga pares ng mga halaga ang kukuha ng parehong dami ng espasyo sa bloke?

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 at X
  • B at Y
  • C at K
  • C at Z
  • K at Z
  • Ako at si J
  • J at X
  • Lahat nakalista

SagutinNarito ang mga sipi mula sa dokumentasyon (12.1.0.2) sa pag-iimbak ng iba't ibang uri ng data sa Oracle.

Uri ng Data ng CHAR
Ang uri ng data ng CHAR ay tumutukoy sa isang fixed-length na string ng character sa set ng character ng database. Tinukoy mo ang set ng character ng database kapag nilikha mo ang iyong database. Tinitiyak ng Oracle na ang lahat ng mga halaga na nakaimbak sa isang column ng CHAR ay may haba na tinukoy sa laki sa napiling haba ng semantika. Kung maglalagay ka ng value na mas maikli kaysa sa haba ng column, ilalagay ng Oracle blank-pad ang value sa haba ng column.

VARCHAR2 Uri ng Data
Ang VARCHAR2 data type ay tumutukoy ng variable-length na string ng character sa database character set. Tinukoy mo ang set ng character ng database kapag nilikha mo ang iyong database. Ang Oracle ay nag-iimbak ng isang halaga ng character sa isang VARCHAR2 column nang eksakto kung paano mo ito tinukoy, nang walang anumang blangko-padding, sa kondisyon na ang halaga ay hindi lalampas sa haba ng column.

NUMBER Uri ng Data
Ang NUMBER uri ng data ay nag-iimbak ng zero pati na rin ang positibo at negatibong mga fixed na numero na may ganap na mga halaga mula 1.0 x 10-130 hanggang ngunit hindi kasama ang 1.0 x 10126. Kung tutukuyin mo ang isang arithmetic expression na ang halaga ay may absolute value na mas malaki kaysa o katumbas ng 1.0 x 10126, pagkatapos ay nagbabalik ang Oracle ng isang error. Ang bawat NUMBER value ay nangangailangan ng mula 1 hanggang 22 byte. Isinasaalang-alang ito, ang laki ng column sa mga byte para sa isang partikular na numeric data value na NUMBER(p), kung saan ang p ay ang katumpakan ng isang ibinigay na halaga, ay maaaring kalkulahin gamit ang sumusunod na formula: ROUND((haba(p)+s)/2))+1 kung saan ang s ay katumbas ng zero kung ang numero ay positibo, at ang s ay katumbas ng 1 kung ang numero ay negatibo.

Bilang karagdagan, kumuha tayo ng isang sipi mula sa dokumentasyon tungkol sa pag-iimbak ng mga Null na halaga.

Ang null ay ang kawalan ng value sa isang column. Ang mga null ay nagpapahiwatig ng nawawala, hindi alam, o hindi naaangkop na data. Ang mga null ay iniimbak sa database kung sila ay nasa pagitan ng mga column na may mga halaga ng data. Sa mga kasong ito, nangangailangan sila ng 1 byte upang maiimbak ang haba ng column (zero). Ang mga sumusunod na null sa isang row ay hindi nangangailangan ng storage dahil ang isang bagong row header ay nagpapahiwatig na ang natitirang mga column sa nakaraang row ay null. Halimbawa, kung ang huling tatlong column ng isang table ay null, walang data na nakaimbak para sa mga column na ito.

Batay sa mga datos na ito, bumuo kami ng pangangatwiran. Ipinapalagay namin na ang database ay gumagamit ng AL32UTF8 encoding. Sa pag-encode na ito, ang mga letrang Ruso ay sasakupin ng 2 byte.

1) A at X, ang halaga ng field na isang 'Y' ay tumatagal ng 1 byte, ang halaga ng field x 'D' ay tumatagal ng 2 byte
2) B at Y, 'Vasya' sa b ang value ay lagyan ng mga puwang na hanggang 10 character at kukuha ng 14 byte, ang 'Vasya' sa d ay kukuha ng 8 byte.
3) C at K. Ang parehong mga patlang ay may halagang NULL, pagkatapos ng mga ito ay may makabuluhang mga patlang, kaya sila ay sumasakop ng 1 byte.
4) C at Z. Ang parehong mga patlang ay may halagang NULL, ngunit ang patlang na Z ay ang huli sa talahanayan, kaya hindi ito tumatagal ng espasyo (0 byte). Sinasakop ng Field C ang 1 byte.
5) K at Z. Katulad ng nakaraang kaso. Ang halaga sa field ng K ay sumasakop ng 1 byte, sa Z – 0.
6) I at J. Ayon sa dokumentasyon, ang parehong mga halaga ay kukuha ng 2 bytes. Kinakalkula namin ang haba gamit ang formula na kinuha mula sa dokumentasyon: round( (1 + 0)/2) +1 = 1 + 1 = 2.
7) J at X. Ang halaga sa J field ay kukuha ng 2 byte, ang halaga sa X field ay kukuha ng 2 byte.

Sa kabuuan, ang mga tamang opsyon ay: C at K, I at J, J at X.

Ano ang tinatayang magiging clustering factor ng T_I index?

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

  • Mga sampu
  • Mga daan-daan
  • Mga libo-libo
  • Mga sampu-sampung libo

SagutinAyon sa dokumentasyon ng Oracle (sinipi mula sa 12.1):

Para sa isang B-tree index, ang index clustering factor ay sumusukat sa pisikal na pagpapangkat ng mga row kaugnay ng isang index value.

Ang index clustering factor ay tumutulong sa optimizer na magpasya kung ang isang index scan o full table scan ay mas mahusay para sa ilang partikular na query). Ang mababang clustering factor ay nagpapahiwatig ng mahusay na index scan.

Ang clustering factor na malapit sa bilang ng mga block sa isang table ay nagpapahiwatig na ang mga row ay pisikal na nakaayos sa mga table block ng index key. Kung ang database ay nagsasagawa ng isang buong pag-scan ng talahanayan, ang database ay may posibilidad na makuha ang mga hilera habang sila ay naka-imbak sa disk na pinagsunod-sunod ng index key. Ang clustering factor na malapit sa bilang ng mga row ay nagpapahiwatig na ang mga row ay random na nakakalat sa mga bloke ng database kaugnay ng index key. Kung ang database ay nagsasagawa ng isang buong pag-scan ng talahanayan, kung gayon ang database ay hindi kukuha ng mga hilera sa anumang pinagsunod-sunod na pagkakasunud-sunod ng index key na ito.

Sa kasong ito, ang data ay perpektong pinagsunod-sunod, kaya ang clustering factor ay magiging katumbas o malapit sa bilang ng mga inookupahang bloke sa talahanayan. Para sa isang karaniwang sukat ng bloke na 8 kilobytes, maaari mong asahan na ang tungkol sa isang libong makitid na halaga ng numero ay magkakasya sa isang bloke, kaya ang bilang ng mga bloke, at bilang isang resulta, ang clustering factor ay magiging mga sampu.

Sa anong mga halaga ng N ang sumusunod na script ay matagumpay na maipapatupad sa isang regular na database na may mga karaniwang setting?

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

SagutinAyon sa dokumentasyon ng Oracle (sinipi mula sa 11.2):

Mga Limitasyon ng Lohikal na Database

Bagay
Uri ng Limitasyon
Limitahan ang Halaga

Ini-index
Kabuuang laki ng na-index na column
75% ng laki ng bloke ng database minus ilang overhead

Kaya, ang kabuuang sukat ng mga na-index na column ay hindi dapat lumampas sa 6Kb. Ang susunod na mangyayari ay depende sa napiling base encoding. Para sa pag-encode ng AL32UTF8, ang isang character ay maaaring sumakop ng maximum na 4 byte, kaya sa pinakamasamang sitwasyon, humigit-kumulang 6 mga character ang magkakasya sa 1500 na kilobytes. Samakatuwid, hindi papayagan ng Oracle ang paggawa ng index sa N = 400 (kapag ang pinakamasamang kaso ng haba ng key ay 1600 character * 4 bytes + rowid na haba), habang sa N = 200 (o mas mababa) ang paglikha ng index ay gagana nang walang mga problema.

Ang INSERT operator na may APPEND na pahiwatig ay idinisenyo upang i-load ang data sa direktang mode. Ano ang mangyayari kung inilapat ito sa talahanayan kung saan nakabitin ang gatilyo?

  • Ilo-load ang data sa direct mode, gagana ang trigger gaya ng inaasahan
  • Ang data ay ilo-load sa direktang mode, ngunit ang trigger ay hindi isasagawa
  • Ilo-load ang data sa conventional mode, gagana ang trigger ayon sa nararapat
  • Ang data ay ilo-load sa conventional mode, ngunit ang trigger ay hindi isasagawa
  • Ang data ay hindi mai-load, ang isang error ay itatala

SagutinTalaga, ito ay higit pa sa isang katanungan ng lohika. Upang mahanap ang tamang sagot, imumungkahi ko ang sumusunod na modelo ng pangangatwiran:

  1. Ang pagpasok sa direktang mode ay ginagawa sa pamamagitan ng direktang pagbuo ng isang bloke ng data, na lumalampas sa SQL engine, na nagsisiguro ng mataas na bilis. Kaya, ang pagtiyak sa pagpapatupad ng trigger ay napakahirap, kung hindi imposible, at walang punto dito, dahil ito ay radikal na magpapabagal sa pagpasok.
  2. Ang pagkabigong isagawa ang trigger ay hahantong sa katotohanan na, kung ang data sa talahanayan ay pareho, ang estado ng database sa kabuuan (iba pang mga talahanayan) ay magdedepende sa mode kung saan ang data na ito ay ipinasok. Malinaw na sisirain nito ang integridad ng data at hindi mailalapat bilang solusyon sa produksyon.
  3. Ang kawalan ng kakayahan na gawin ang hiniling na operasyon ay karaniwang itinuturing na isang error. Ngunit dito dapat nating tandaan na ang APPEND ay isang pahiwatig, at ang pangkalahatang lohika ng mga pahiwatig ay ang mga ito ay isinasaalang-alang kung maaari, ngunit kung hindi, ang operator ay isinasagawa nang hindi isinasaalang-alang ang pahiwatig.

Kaya ang inaasahang sagot ay ilo-load ang data sa normal (SQL) mode, gagana ang trigger.

Ayon sa dokumentasyon ng Oracle (sinipi mula sa 8.04):

Ang mga paglabag sa mga paghihigpit ay magiging sanhi ng pahayag na isagawa nang sunud-sunod, gamit ang karaniwang insert path, nang walang mga babala o mensahe ng error. Ang isang pagbubukod ay ang paghihigpit sa mga pahayag na nag-a-access sa parehong talahanayan nang higit sa isang beses sa isang transaksyon, na maaaring magdulot ng mga mensahe ng error.
Halimbawa, kung ang mga trigger o referential integrity ay nasa talahanayan, ang APPEND na hint ay hindi papansinin kapag sinubukan mong gumamit ng direct-load na INSERT (serial o parallel), gayundin ang PARALLEL na hint o clause, kung mayroon man.

Ano ang mangyayari kapag ang sumusunod na script ay naisakatuparan?

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

  • Ang matagumpay na pagpapatupad
  • Nabigo dahil sa syntax error
  • Error: Hindi Wasto ang Autonomous na Transaksyon
  • Error na nauugnay sa paglampas sa maximum na call nesting
  • Error sa Paglabag sa Foreign Key
  • Error na nauugnay sa mga lock

SagutinAng talahanayan at trigger ay ginawa nang tama at ang operasyong ito ay hindi dapat humantong sa mga problema. Ang mga autonomous na transaksyon sa isang trigger ay pinapayagan din, kung hindi, ang pag-log ay hindi posible, halimbawa.

Pagkatapos ipasok ang unang row, ang matagumpay na pagpapagana ng trigger ay magdudulot ng pagpasok ng pangalawang row, na magiging sanhi ng paggana muli ng trigger, pagpasok ng pangatlong row, at iba pa hanggang sa mabigo ang statement dahil sa paglampas sa maximum nesting ng mga tawag. Gayunpaman, isa pang banayad na punto ang pumapasok. Sa oras na ang trigger ay naisakatuparan, ang commit ay hindi pa nakumpleto para sa unang ipinasok na tala. Samakatuwid, ang isang trigger na tumatakbo sa isang autonomous na transaksyon ay sumusubok na magpasok sa talahanayan ng isang row na tumutukoy sa isang dayuhang key sa isang tala na hindi pa nagagawa. Nagreresulta ito sa isang paghihintay (ang autonomous na transaksyon ay naghihintay para sa pangunahing transaksyon na i-commit upang makita kung maaari itong magpasok ng data) at sa parehong oras ang pangunahing transaksyon ay naghihintay para sa autonomous na transaksyon na magpatuloy sa paggana pagkatapos ng trigger. Nangyayari ang deadlock at, bilang resulta, nakansela ang autonomous na transaksyon dahil sa mga kadahilanang nauugnay sa mga lock.

Ang mga rehistradong user lamang ang maaaring lumahok sa survey. Mag-sign in, pakiusap

Ito ay mahirap na?

  • Tulad ng dalawang daliri, napagpasyahan ko kaagad ang lahat ng tama.

  • Hindi talaga, nagkamali ako sa ilang tanong.

  • Nalutas ko nang tama ang kalahati nito.

  • Dalawang beses kong nahulaan ang sagot!

  • Magsusulat ako sa mga komento

14 user ang bumoto. 10 na user ang umiwas.

Pinagmulan: www.habr.com

Magdagdag ng komento