По стапките на Highload++ Siberia 2019 - 8 задачи на Oracle

Здраво!

На 24-25 јуни, во Новосибирск се одржа конференцијата Highload++ Siberia 2019. Таму беа и нашите момци извештај „Oracle контејнерски бази на податоци (CDB/PDB) и нивна практична употреба за развој на софтвер“, ќе објавиме текстуална верзија малку подоцна. Беше кул, благодарам олегбунин за организацијата, како и за сите што дојдоа.

По стапките на Highload++ Siberia 2019 - 8 задачи на Oracle
Во овој пост, би сакале да ги споделиме со вас проблемите што ги имавме на нашиот штанд за да можете да го тестирате вашето знаење на Oracle. Под резот има 8 проблеми, опции за одговори и објаснување.

Која е максималната вредност на низата што ќе ја видиме како резултат на извршување на следната скрипта?

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
  • Не, ќе има грешка

ОдговориСпоред документацијата на Oracle (цитиран од 8.1.6):
Во рамките на една SQL изјава, Oracle ќе ја зголеми низата само еднаш по ред. Ако изјавата содржи повеќе од една референца за NEXTVAL за секвенца, Oracle ја зголемува низата еднаш и ја враќа истата вредност за сите појави на NEXTVAL. Ако изјавата содржи референци и за CURRVAL и за NEXTVAL, Oracle ја зголемува низата и ја враќа истата вредност и за CURRVAL и за NEXTVAL без оглед на нивниот редослед во исказот.

Така, максималната вредност ќе одговара на бројот на линии, односно 5.

Колку редови ќе има во табелата како резултат на извршување на следната скрипта?

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

ОдговориСпоред документацијата на Oracle (цитиран од 11.2):

Пред извршување на која било изјава SQL, Oracle означува имплицитна точка за зачувување (не е достапна за вас). Потоа, ако изјавата не успее, Oracle автоматски ја враќа назад и го враќа применливиот код за грешка во SQLCODE во SQLCA. На пример, ако изјавата INSERT предизвика грешка со обидот да се вметне дупликат вредност во единствен индекс, изјавата се враќа назад.

Повикувањето на HP од клиентот исто така се смета и обработува како единствена изјава. Така, првиот повик на HP заврши успешно, со вметнати три записи; вториот повик на HP завршува со грешка и го враќа четвртиот запис што успеал да го вметне; третиот повик не успее, а во табелата има три записи.

Колку редови ќе има во табелата како резултат на извршување на следната скрипта?

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

ОдговориСпоред документацијата на Oracle (цитиран од 11.2):

Ограничувањето за проверка ви овозможува да наведете услов што секој ред во табелата мора да го исполнува. За да се задоволи ограничувањето, секој ред во табелата мора да го направи условот или ТОЧЕН или непознат (поради нула). Кога Oracle проценува услов за ограничување за проверка за одреден ред, сите имиња на колони во условот се однесуваат на вредностите на колоните во тој ред.

Така, вредноста null ќе ја помине проверката, а анонимниот блок ќе биде успешно извршен до обидот да се вметне вредноста 3. После ова, блокот за справување со грешки ќе го избрише исклучокот, нема да се случи враќање назад, и ќе останат четири реда во табелата со вредности 1, нула, 2 и повторно нула.

Кои пара вредности ќе заземат иста количина на простор во блокот?

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

  • А и Х
  • Б и Ј
  • Ц и К
  • Ц и З
  • К и З
  • Јас и Ј
  • Ј и Х
  • Сите наведени

ОдговориЕве извадоци од документацијата (12.1.0.2) за складирање на различни видови податоци во Oracle.

CHAR Тип на податоци
Типот на податоци CHAR одредува низа знаци со фиксна должина во множеството знаци на базата на податоци. Вие го одредувате множеството карактери на базата на податоци кога ја креирате вашата база на податоци. Oracle гарантира дека сите вредности зачувани во колона CHAR ја имаат должината одредена по големина во семантиката на избраната должина. Ако вметнете вредност што е пократка од должината на колоната, тогаш Oracle празно ја префрла вредноста на должината на колоната.

VARCHAR2 Тип на податоци
Типот на податоци VARCHAR2 одредува низа знаци со променлива должина во множеството знаци на базата на податоци. Вие го одредувате множеството карактери на базата на податоци кога ја креирате вашата база на податоци. Oracle зачувува вредност на знаци во колона VARCHAR2 токму онака како што ја наведовте, без празно полнење, под услов вредноста да не ја надминува должината на колоната.

NUMBER Тип на податоци
Типот на податоци NUMBER складира нула, како и позитивни и негативни фиксни броеви со апсолутни вредности од 1.0 x 10-130 до, но не вклучувајќи 1.0 x 10126. Ако наведете аритметички израз чија вредност има апсолутна вредност поголема или еднаква на 1.0 x 10126, потоа Oracle враќа грешка. Секоја вредност на NUMBER бара од 1 до 22 бајти. Земајќи го ова предвид, големината на колоната во бајти за одредена вредност на нумерички податоци NUMBER(p), каде што p е прецизноста на дадената вредност, може да се пресмета со помош на следнава формула: ROUND((должина(p)+s)/2))+1 каде што s е еднакво на нула ако бројот е позитивен, а s е еднаков на 1 ако бројот е негативен.

Во продолжение, да земеме извадок од документацијата за складирање на Null вредности.

Нулта е отсуство на вредност во колона. Нултите укажуваат на исчезнати, непознати или неприменливи податоци. Нуловите се зачувуваат во базата на податоци доколку паднат помеѓу колони со вредности на податоци. Во овие случаи, тие бараат 1 бајт за складирање на должината на колоната (нула). Задоцнетите нула по ред не бараат складирање бидејќи новото заглавие на редот сигнализира дека преостанатите колони во претходниот ред се нула. На пример, ако последните три колони од табелата се нула, тогаш не се складираат податоци за овие колони.

Врз основа на овие податоци, градиме расудување. Претпоставуваме дека базата на податоци користи кодирање AL32UTF8. Во ова кодирање, руските букви ќе заземаат 2 бајти.

1) A и X, вредноста на полето a 'Y' зема 1 бајт, вредноста на полето x 'D' зема 2 бајти
2) B и Y, „Vasya“ во b вредноста ќе биде пополнета со празни места до 10 знаци и ќе потрае 14 бајти, „Vasya“ во d ќе потрае 8 бајти.
3) C и K. Двете полиња имаат вредност NULL, по нив има значајни полиња, па зафаќаат 1 бајт.
4) C и Z. Двете полиња имаат вредност NULL, но полето Z е последно во табелата, така што не зафаќа простор (0 бајти). Полето C зафаќа 1 бајт.
5) K и Z. Слично на претходниот случај. Вредноста во полето K зафаќа 1 бајт, во Z – 0.
6) I и J. Според документацијата, двете вредности ќе потраат 2 бајти. Ја пресметуваме должината користејќи ја формулата земена од документацијата: круг( (1 + 0)/2) +1 = 1 + 1 = 2.
7) J и X. Вредноста во полето J ќе потрае 2 бајти, вредноста во полето X ќе потрае 2 бајти.

Севкупно, точните опции се: C и K, I и J, J и X.

Колку приближно ќе биде факторот на кластерирање на индексот T_I?

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

  • Околу десетици
  • Околу стотици
  • Околу илјадници
  • Околу десетици илјади

ОдговориСпоред документацијата на Oracle (цитиран од 12.1):

За индекс Б-дрво, факторот за кластерирање на индексот го мери физичкото групирање на редовите во однос на вредноста на индексот.

Факторот за групирање на индекси му помага на оптимизаторот да одлучи дали скенирањето на индекс или скенирањето на целосната табела е поефикасно за одредени прашања). Нискиот фактор на групирање укажува на ефикасно скенирање на индексот.

Фактор на кластерирање кој е блиску до бројот на блокови во табелата покажува дека редовите се физички подредени во блоковите на табелата со индексниот клуч. Ако базата на податоци изврши целосно скенирање на табелите, тогаш базата има тенденција да ги поврати редовите како што се складирани на дискот подредени според индексниот клуч. Фактор на кластерирање кој е блиску до бројот на редови покажува дека редовите се расфрлани случајно низ блоковите на базата на податоци во однос на индексниот клуч. Ако базата на податоци изврши целосно скенирање на табелите, тогаш базата на податоци нема да враќа редови во кој било подреден редослед според овој индексен клуч.

Во овој случај, податоците се идеално подредени, така што факторот на кластерирање ќе биде еднаков или близок до бројот на окупирани блокови во табелата. За стандардна големина на блок од 8 килобајти, можете да очекувате дека околу илјада тесни броевни вредности ќе се вклопат во еден блок, така што бројот на блокови и како резултат на тоа, факторот за групирање ќе биде околу десетици.

Со кои вредности на N ќе се изврши успешно следнава скрипта во редовна база на податоци со стандардни поставки?

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

ОдговориСпоред документацијата на Oracle (цитиран од 11.2):

Логички ограничувања на базата на податоци

Содржина
Вид на ограничување
Гранична вредност

Индекси
Вкупна големина на индексирана колона
75% од големината на блокот на базата на податоци минус некои трошоци

Така, вкупната големина на индексираните колони не треба да надминува 6Kb. Што ќе се случи понатаму зависи од избраното основно кодирање. За кодирање AL32UTF8, еден знак може да зафаќа максимум 4 бајти, така што во најлошото сценарио, околу 6 знаци ќе се вклопат во 1500 килобајти. Затоа, Oracle нема да дозволи создавање индекси на N = 400 (кога должината на клучот во најлош случај е 1600 карактери * 4 бајти + должина на ред), додека на N = 200 (или помалку) создавањето на индексот ќе работи без проблеми.

Операторот INSERT со навестување APPEND е дизајниран да вчитува податоци во директен режим. Што се случува ако се нанесе на масата на која виси чкрапалото?

  • Податоците ќе се вчитаат во директен режим, активирањето ќе работи како што се очекуваше
  • Податоците ќе се вчитаат во директен режим, но активирањето нема да се изврши
  • Податоците ќе се вчитаат во конвенционален режим, активирањето ќе работи како што треба
  • Податоците ќе се вчитаат во конвенционален режим, но активирањето нема да се изврши
  • Податоците нема да се вчитаат, ќе се евидентира грешка

ОдговориВо суштина, ова е повеќе прашање на логика. За да го најдете точниот одговор, би го предложил следниов модел на расудување:

  1. Вметнувањето во директен режим се врши со директно формирање на блок на податоци, заобиколувајќи го моторот SQL, што обезбедува голема брзина. Така, обезбедувањето на извршувањето на активирањето е многу тешко, ако не и невозможно, и нема смисла во тоа, бидејќи сепак радикално ќе го забави вметнувањето.
  2. Неуспехот да се изврши активирањето ќе доведе до фактот дека, ако податоците во табелата се исти, состојбата на базата на податоци како целина (други табели) ќе зависи од режимот во кој се вметнати овие податоци. Ова очигледно ќе го уништи интегритетот на податоците и не може да се примени како решение во производството.
  3. Неможноста да се изврши бараната операција генерално се третира како грешка. Но, тука треба да запомниме дека APPEND е навестување, а општата логика на навестувањата е дека тие се земаат предвид ако е можно, но ако не, операторот се извршува без да се земе предвид навестувањето.

Значи очекуваниот одговор е податоците ќе се вчитаат во нормален (SQL) режим, активирањето ќе се активира.

Според документацијата на Oracle (цитиран од 8.04):

Прекршувањето на ограничувањата ќе предизвика изјавата да се извршува сериски, користејќи ја конвенционалната патека за вметнување, без предупредувања или пораки за грешка. Исклучок е ограничувањето на изјавите кои пристапуваат до истата табела повеќе пати во трансакцијата, што може да предизвика пораки за грешка.
На пример, ако на табелата се присутни активирачи или референцијален интегритет, тогаш советот APPEND ќе се игнорира кога ќе се обидете да користите INSERT со директно оптоварување (сериски или паралелно), како и навестувањето или клаузулата PARALLEL, доколку ги има.

Што ќе се случи кога ќе се изврши следната скрипта?

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

  • Успешно извршување
  • Неуспех поради синтаксна грешка
  • Грешка: автономната трансакција не е валидна
  • Грешка поврзана со надминување на максималното вгнездување повици
  • Грешка при прекршување на странски клуч
  • Грешка поврзана со бравите

ОдговориТабелата и активирањето се создадени сосема правилно и оваа операција не треба да доведе до проблеми. Дозволени се и автономни трансакции во активирач, инаку евидентирањето не би било можно, на пример.

По вметнувањето на првиот ред, успешното палење на чкрапалото би предизвикало вметнување на вториот ред, што предизвикува активирање на чкрапалото повторно, вметнување трет ред и така натаму додека изјавата не пропадне поради надминување на максималното вгнездување на повици. Сепак, уште една суптилна точка доаѓа во игра. Во моментот кога активирањето е извршено, извршувањето сè уште не е завршено за првиот вметнат запис. Затоа, активирањето кое работи во автономна трансакција се обидува да вметне во табелата ред кој упатува на странски клуч на запис кој сè уште не е извршен. Ова резултира со чекање (автономната трансакција чека главната трансакција да се изврши за да види дали може да вметне податоци) и во исто време главната трансакција чека автономната трансакција да продолжи да работи по активирањето. Настанува ќор-сокак и, како резултат на тоа, автономната трансакција е откажана поради причини поврзани со брави.

Само регистрирани корисници можат да учествуваат во анкетата. Најави се, вие сте добредојдени.

Беше тешко да?

  • Како два прста, веднаш решив сè правилно.

  • Не баш, згрешив на неколку прашања.

  • Пола од тоа решив правилно.

  • Го погодив одговорот двапати!

  • Ќе напишам во коментарите

Гласаа 14 корисници. 10 корисници беа воздржани.

Извор: www.habr.com

Додадете коментар