Seguint els passos de Highload++ Siberia 2019 - 8 tasques a Oracle

Hi!

Del 24 al 25 de juny es va celebrar a Novosibirsk la conferència Highload++ Siberia 2019. Els nostres nois també hi van ser informe “Les bases de dades de contenidors Oracle (CDB/PDB) i el seu ús pràctic per al desenvolupament de programari”, publicarem una versió de text una mica més endavant. Va ser genial, gràcies olegbunin per a l'organització, així com per a tothom que va venir.

Seguint els passos de Highload++ Siberia 2019 - 8 tasques a Oracle
En aquesta publicació, ens agradaria compartir amb vosaltres els problemes que vam tenir al nostre estand perquè pugueu posar a prova els vostres coneixements d'Oracle. A sota del tall hi ha 8 problemes, opcions de resposta i explicació.

Quin és el valor màxim de la seqüència que veurem com a resultat d'executar l'script següent?

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
  • No, hi haurà un error

RespondreSegons la documentació d'Oracle (citada de 8.1.6):
Dins d'una sola instrucció SQL, Oracle incrementarà la seqüència només una vegada per fila. Si una instrucció conté més d'una referència a NEXTVAL per a una seqüència, Oracle incrementa la seqüència una vegada i retorna el mateix valor per a totes les ocurrències de NEXTVAL. Si una instrucció conté referències tant a CURRVAL com a NEXTVAL, l'Oracle augmenta la seqüència i retorna el mateix valor tant per a CURRVAL com per NEXTVAL independentment de l'ordre que tinguin dins de la instrucció.

Per tant, la el valor màxim correspondrà al nombre de línies, és a dir, 5.

Quantes files hi haurà a la taula com a resultat d'executar l'script següent?

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

RespondreSegons la documentació d'Oracle (citada de 11.2):

Abans d'executar qualsevol instrucció SQL, Oracle marca un punt de salvament implícit (no disponible per a vostè). Aleshores, si la instrucció falla, Oracle la torna automàticament i retorna el codi d'error aplicable a SQLCODE a l'SQLCA. Per exemple, si una instrucció INSERT provoca un error en intentar inserir un valor duplicat en un índex únic, la sentència es revertirà.

La trucada a HP des del client també es considera i es processa com una sola declaració. Així, la primera trucada d'HP es completa amb èxit, havent inserit tres registres; la segona trucada d'HP acaba amb un error i fa retrocedir el quart registre que ha aconseguit inserir; la tercera trucada falla, i hi ha tres registres a la taula.

Quantes files hi haurà a la taula com a resultat d'executar l'script següent?

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

RespondreSegons la documentació d'Oracle (citada de 11.2):

Una restricció de verificació us permet especificar una condició que ha de complir cada fila de la taula. Per satisfer la restricció, cada fila de la taula ha de fer que la condició sigui TRUE o desconeguda (a causa d'un null). Quan Oracle avalua una condició de restricció de verificació per a una fila determinada, els noms de columna de la condició fan referència als valors de la columna d'aquesta fila.

Així, el valor null passarà la comprovació i el bloc anònim s'executarà correctament fins que s'intenta inserir el valor 3. Després d'això, el bloc de gestió d'errors esborrarà l'excepció, no es produirà cap retrocés i quedaran quatre files a la taula amb valors 1, nul, 2 i nul de nou.

Quins parells de valors ocuparan la mateixa quantitat d'espai al bloc?

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
  • jo i J
  • J i X
  • Tot llistat

RespondreAquí hi ha extractes de la documentació (12.1.0.2) sobre l'emmagatzematge de diversos tipus de dades a Oracle.

Tipus de dades CHAR
El tipus de dades CHAR especifica una cadena de caràcters de longitud fixa al conjunt de caràcters de la base de dades. Especifiqueu el conjunt de caràcters de la base de dades quan creeu la vostra base de dades. Oracle assegura que tots els valors emmagatzemats en una columna CHAR tinguin la longitud especificada per mida a la semàntica de longitud seleccionada. Si inseriu un valor que és més curt que la longitud de la columna, l'Oracle afegeix el valor a la longitud de la columna.

VARCHAR2 Tipus de dades
El tipus de dades VARCHAR2 especifica una cadena de caràcters de longitud variable al conjunt de caràcters de la base de dades. Especifiqueu el conjunt de caràcters de la base de dades quan creeu la vostra base de dades. L'Oracle emmagatzema un valor de caràcter en una columna VARCHAR2 exactament tal com l'especifiqueu, sense cap encoixinat en blanc, sempre que el valor no superi la longitud de la columna.

NUMBER Tipus de dades
El tipus de dades NUMBER emmagatzema zero, així com nombres fixos positius i negatius amb valors absoluts d'1.0 x 10-130 a 1.0 x 10126, però sense incloure. Si especifiqueu una expressió aritmètica el valor de la qual té un valor absolut superior o igual a 1.0 x 10126, llavors Oracle retorna un error. Cada valor NUMBER requereix d'1 a 22 bytes. Tenint això en compte, la mida de la columna en bytes per a un valor de dades numèrics NUMBER(p), on p és la precisió d'un valor donat, es pot calcular mitjançant la fórmula següent: RODONA((longitud (p)+s)/2))+1 on s és igual a zero si el nombre és positiu, i s és igual a 1 si el nombre és negatiu.

A més, agafem un fragment de la documentació sobre l'emmagatzematge de valors nuls.

Un null és l'absència d'un valor en una columna. Els nulls indiquen dades que falten, desconegudes o inaplicables. Els valors nuls s'emmagatzemen a la base de dades si es troben entre columnes amb valors de dades. En aquests casos, necessiten 1 byte per emmagatzemar la longitud de la columna (zero). Els valors nuls al final d'una fila no requereixen emmagatzematge perquè una nova capçalera de fila indica que les columnes restants de la fila anterior són nul·les. Per exemple, si les últimes tres columnes d'una taula són nul·les, no s'emmagatzemen dades per a aquestes columnes.

A partir d'aquestes dades, construïm un raonament. Suposem que la base de dades utilitza la codificació AL32UTF8. En aquesta codificació, les lletres russes ocuparan 2 bytes.

1) A i X, el valor del camp a 'Y' pren 1 byte, el valor del camp x 'D' pren 2 bytes
2) B i Y, 'Vasya' a b, el valor s'emplenarà amb espais de fins a 10 caràcters i trigarà 14 bytes, 'Vasya' a d trigarà 8 bytes.
3) C i K. Tots dos camps tenen el valor NULL, després d'ells hi ha camps significatius, de manera que ocupen 1 byte.
4) C i Z. Tots dos camps tenen el valor NULL, però el camp Z és l'últim de la taula, de manera que no ocupa espai (0 bytes). El camp C ocupa 1 byte.
5) K i Z. Similar al cas anterior. El valor del camp K ocupa 1 byte, en Z – 0.
6) I i J. Segons la documentació, ambdós valors trigaran 2 bytes. Calculem la longitud mitjançant la fórmula extreta de la documentació: round( (1 + 0)/2) +1 = 1 + 1 = 2.
7) J i X. El valor del camp J trigarà 2 bytes, el valor del camp X trigarà 2 bytes.

En total, les opcions correctes són: C i K, I i J, J i X.

Quin serà aproximadament el factor de agrupació de l'índex 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);

  • Unes desenes
  • Uns centenars
  • Uns milers
  • Unes desenes de milers

RespondreSegons la documentació d'Oracle (citada de 12.1):

Per a un índex d'arbre B, el factor de agrupació d'índexs mesura l'agrupació física de files en relació amb un valor d'índex.

El factor d'agrupació d'índexs ajuda l'optimitzador a decidir si una exploració d'índexs o una exploració de taula completa és més eficient per a determinades consultes). Un factor d'agrupament baix indica una exploració d'índex eficient.

Un factor d'agrupació que s'aproxima al nombre de blocs d'una taula indica que les files estan ordenades físicament als blocs de la taula per la clau d'índex. Si la base de dades realitza una exploració completa de la taula, la base de dades tendeix a recuperar les files a mesura que s'emmagatzemen al disc ordenades per la clau d'índex. Un factor d'agrupació que s'aproxima al nombre de files indica que les files estan disperses aleatòriament pels blocs de la base de dades en relació amb la clau d'índex. Si la base de dades realitza una exploració completa de la taula, la base de dades no recuperaria les files en cap ordre ordenat per aquesta clau d'índex.

En aquest cas, les dades s'ordenen de manera ideal, de manera que el factor d'agrupació serà igual o proper al nombre de blocs ocupats a la taula. Per a una mida de bloc estàndard de 8 kilobytes, podeu esperar que uns mil valors de nombres estrets encaixin en un bloc, de manera que el nombre de blocs i, com a resultat, el factor d'agrupació serà unes desenes.

A quins valors de N s'executarà amb èxit el següent script en una base de dades normal amb configuració estàndard?

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

RespondreSegons la documentació d'Oracle (citada de 11.2):

Límits de la base de dades lògica

Article
Tipus de límit
Valor límit

Índexs
Mida total de la columna indexada
El 75% de la mida del bloc de la base de dades menys una mica de sobrecàrrega

Per tant, la mida total de les columnes indexades no hauria de superar els 6 Kb. El que passa a continuació depèn de la codificació base seleccionada. Per a la codificació AL32UTF8, un caràcter pot ocupar un màxim de 4 bytes, de manera que, en el pitjor dels casos, uns 6 caràcters encaixaran en 1500 kilobytes. Per tant, Oracle no permetrà la creació d'índex a N = 400 (quan la longitud de la clau del pitjor cas és de 1600 caràcters * 4 bytes + longitud de rowid), mentre que a N = 200 (o menys) la creació de l'índex funcionarà sense problemes.

L'operador INSERT amb la pista APPEND està dissenyat per carregar dades en mode directe. Què passa si s'aplica a la taula on penja el disparador?

  • Les dades es carregaran en mode directe, el disparador funcionarà com s'esperava
  • Les dades es carregaran en mode directe, però el disparador no s'executarà
  • Les dades es carregaran en mode convencional, el disparador funcionarà com cal
  • Les dades es carregaran en mode convencional, però el disparador no s'executarà
  • Les dades no es carregaran, es registrarà un error

RespondreBàsicament, això és més una qüestió de lògica. Per trobar la resposta correcta, suggeriria el següent model de raonament:

  1. La inserció en mode directe es realitza mitjançant la formació directa d'un bloc de dades, sense passar pel motor SQL, que garanteix una alta velocitat. Així, assegurar l'execució del disparador és molt difícil, si no impossible, i això no té sentit, ja que encara alentirà radicalment la inserció.
  2. La manca d'execució del disparador comportarà que, si les dades de la taula són les mateixes, l'estat de la base de dades en el seu conjunt (altres taules) dependrà del mode en què s'han inserit aquestes dades. Això, òbviament, destruirà la integritat de les dades i no es pot aplicar com a solució en producció.
  3. La incapacitat de realitzar l'operació sol·licitada es considera generalment un error. Però aquí hem de recordar que APPEND és una pista, i la lògica general de les pistes és que es tenen en compte si és possible, però si no, l'operador s'executa sense tenir en compte la pista.

Així que la resposta esperada és les dades es carregaran en mode normal (SQL), el disparador es dispararà.

Segons la documentació d'Oracle (citada de 8.04):

Les infraccions de les restriccions provocaran que la instrucció s'executi en sèrie, utilitzant el camí d'inserció convencional, sense avisos ni missatges d'error. Una excepció és la restricció a les declaracions que accedeixen a la mateixa taula més d'una vegada en una transacció, que pot provocar missatges d'error.
Per exemple, si hi ha activadors o integritat referencial a la taula, la pista APPEND s'ignorarà quan intenteu utilitzar INSERT de càrrega directa (en sèrie o paral·lel), així com la pista o clàusula PARALLEL, si n'hi ha.

Què passarà quan s'executi el següent script?

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

  • Finalització satisfactòria
  • Error a causa d'un error de sintaxi
  • Error: la transacció autònoma no és vàlida
  • Error relacionat amb la superació de l'imbricació màxima de trucades
  • Error de violació de clau estrangera
  • Error relacionat amb els panys

RespondreLa taula i el disparador es creen correctament i aquesta operació no hauria de generar problemes. També es permeten les transaccions autònomes en un disparador, en cas contrari no seria possible el registre, per exemple.

Després d'inserir la primera fila, un disparador amb èxit provocaria que s'inserís la segona fila, provocant que el disparador torni a disparar, inserint una tercera fila, i així successivament fins que la instrucció fallava perquè s'ha superat l'imbricació màxima de trucades. Tanmateix, entra en joc un altre punt subtil. En el moment en què s'executa l'activador, la confirmació encara no s'ha completat per al primer registre inserit. Per tant, un activador que s'executa en una transacció autònoma intenta inserir a la taula una fila que fa referència a una clau estrangera a un registre que encara no s'ha confirmat. Això provoca una espera (la transacció autònoma espera que la transacció principal es comprometi per veure si pot inserir dades) i alhora la transacció principal espera que la transacció autònoma continuï funcionant després del disparador. Es produeix un bloqueig i, com a conseqüència, la transacció autònoma es cancel·la per motius relacionats amb els bloquejos..

Només els usuaris registrats poden participar en l'enquesta. Inicia sessiósi us plau.

Va ser difícil?

  • Com dos dits, de seguida ho vaig decidir tot correctament.

  • Realment no, m'he equivocat en un parell de preguntes.

  • Vaig resoldre la meitat correctament.

  • Vaig endevinar la resposta dues vegades!

  • Escriuré als comentaris

Han votat 14 usuaris. 10 usuaris es van abstenir.

Font: www.habr.com

Afegeix comentari