Suite à Highload ++ Siberia 2019 - 8 tâches Oracle

Salut

Du 24 au 25 juin, la conférence Highload ++ Siberia 2019 s'est tenue à Novossibirsk. Nos gars étaient également présents sur le rapport "Oracle Container Bases (CDB / PDB) et leur utilisation pratique pour le développement de logiciels", nous publierons une version texte un peu plus tard. C'était cool, merci olegbunin pour l'organisation, ainsi que tous ceux qui sont venus.


Dans cet article, nous aimerions partager avec vous les tâches qui étaient sur notre stand afin que vous puissiez tester vos connaissances dans Oracle. Sous la coupe - 8 tâches, options de réponse et explication.

Quelle est la valeur maximale de la séquence que nous verrons à la suite du script suivant?


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
  • Non, il y aura une erreur

La réponse
Selon la documentation Oracle (citée du 8.1.6):
Dans une seule instruction SQL, Oracle n'incrémentera la séquence qu'une seule fois par ligne. Si une instruction contient plusieurs références à NEXTVAL pour une séquence, Oracle incrémente la séquence une fois et renvoie la même valeur pour toutes les occurrences de NEXTVAL. Si une instruction contient des références à la fois à CURRVAL et à NEXTVAL, Oracle incrémente la séquence et renvoie la même valeur à la fois pour CURRVAL et NEXTVAL quelle que soit leur ordre dans l'instruction.

Ainsi, la valeur maximale correspondra au nombre de lignes, soit 5 .

Combien de lignes y aura-t-il à la suite du script suivant?


 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

La réponse
Selon la documentation Oracle (citée à partir de 11.2):

Avant d'exécuter une instruction SQL, Oracle marque un point de sauvegarde implicite (non disponible pour vous). Ensuite, si l'instruction échoue, Oracle la restaure automatiquement et renvoie le code d'erreur applicable à SQLCODE dans le SQLCA. Par exemple, si une instruction INSERT provoque une erreur en essayant d'insérer une valeur en double dans un index unique, l'instruction est annulée.

Un appel du client est également considéré et traité comme une seule déclaration. Ainsi, le premier appel à HP se termine avec succès en insérant trois enregistrements; le deuxième appel à HP se termine par une erreur et annule le quatrième enregistrement, que j'ai réussi à insérer; le troisième appel échoue et trois entrées apparaissent dans le tableau .

Combien de lignes y aura-t-il à la suite du script suivant?


 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

La réponse
Selon la documentation Oracle (citée à partir de 11.2):

Une contrainte de vérification vous permet de spécifier une condition à laquelle chaque ligne du tableau doit satisfaire. Pour satisfaire la contrainte, chaque ligne du tableau doit rendre la condition TRUE ou inconnue (en raison d'une valeur null). Lorsqu'Oracle évalue une condition de contrainte de vérification pour une ligne particulière, tous les noms de colonne de la condition font référence aux valeurs de colonne de cette ligne.

Ainsi, la valeur nulle passera le test et le bloc anonyme sera exécuté avec succès jusqu'à la tentative d'insertion de la valeur 3. Après cela, le bloc de traitement d'erreur lèvera une exception, la restauration ne se produira pas et la table aura quatre lignes avec les valeurs 1, null, 2 et null à nouveau.

Quelles paires de valeurs occuperont la même quantité d'espace dans le 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 et X
  • B et Y
  • C et K
  • C et Z
  • K et Z
  • I et J
  • J et X
  • Tous listés

La réponse
Voici des extraits de la documentation (12.1.0.2) pour stocker différents types de données dans Oracle.

Type de données char
Le type de données CHAR spécifie une chaîne de caractères de longueur fixe dans le jeu de caractères de la base de données. Vous spécifiez le jeu de caractères de la base de données lorsque vous créez votre base de données. Oracle s'assure que toutes les valeurs stockées dans une colonne CHAR ont la longueur spécifiée par taille dans la sémantique de longueur sélectionnée. Si vous insérez une valeur plus courte que la longueur de la colonne, Oracle vide la valeur à la longueur de la colonne.

Type de données VARCHAR2
Le type de données VARCHAR2 spécifie une chaîne de caractères de longueur variable dans le jeu de caractères de la base de données. Vous spécifiez le jeu de caractères de la base de données lorsque vous créez votre base de données. Oracle stocke une valeur de caractère dans une colonne VARCHAR2 exactement comme vous la spécifiez, sans aucun remplissage blanc, à condition que la valeur ne dépasse pas la longueur de la colonne.

NUMBER Type de données
Le type de données NUMBER stocke zéro ainsi que des nombres fixes positifs et négatifs avec des valeurs absolues de 1,0 x 10-130 à 1,0 X 10126, mais non compris. Si vous spécifiez une expression arithmétique dont la valeur a une valeur absolue supérieure ou égale à 1,0 x 10126, puis Oracle renvoie une erreur. Chaque valeur NUMBER nécessite de 1 à 22 octets. En tenant compte de cela, la taille de la colonne en octets pour une valeur numérique donnée NUMBER (p), où p est la précision d'une valeur donnée, peut être calculée à l'aide de la formule suivante: ROUND ((longueur (p) + s) / 2)) + 1 où s est égal à zéro si le nombre est positif et s est égal à 1 si le nombre est négatif.

De plus, nous prenons un extrait de la documentation sur le stockage des valeurs Null.

Un null est l'absence d'une valeur dans une colonne. Les valeurs nulles indiquent des données manquantes, inconnues ou inapplicables. Les valeurs nulles sont stockées dans la base de données si elles tombent entre des colonnes avec des valeurs de données. Dans ces cas, ils nécessitent 1 octet pour stocker la longueur de la colonne (zéro). Les null à la fin d'une ligne ne nécessitent aucun stockage car un nouvel en-tête de ligne signale que les colonnes restantes de la ligne précédente sont nulles. Par exemple, si les trois dernières colonnes d'une table sont nulles, aucune donnée n'est stockée pour ces colonnes.

Sur la base de ces données, nous construisons un raisonnement. Nous pensons que la base de données utilise le codage AL32UTF8. Dans cet encodage, les lettres russes occuperont 2 octets.

1) A et X, la valeur du champ a 'Y' est de 1 octet, la valeur du champ x 'D' est de 2 octets
2) B et Y, 'Vasya' en valeur b sera complété par des espaces jusqu'à 10 caractères et occupera 14 octets, 'Vasya' en d - prendra 8 octets.
3) C et K. Les deux champs sont NULS, après eux il y a des champs significatifs, donc ils occupent 1 octet.
4) C et Z. Les deux champs sont NULS, mais le champ Z est le dernier de la table, donc il ne prend pas d'espace (0 octet). Le champ C occupe 1 octet.
5) K et Z. Similaire au cas précédent. La valeur dans le champ K est de 1 octet, en Z - 0.
6) I et J. Selon la documentation, les deux valeurs prendront chacune 2 octets. Nous considérons la longueur selon la formule tirée de la documentation: round ((1 + 0) / 2) +1 = 1 + 1 = 2.
7) J et X. La valeur dans le champ J prendra 2 octets, la valeur dans le champ X prendra 2 octets.

Au total, les options correctes sont: C et K, I et J, J et X.


Quel sera le facteur de regroupement de l'indice T_I approximativement?


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

  • Des dizaines
  • Environ des centaines
  • De l'ordre de milliers
  • De l'ordre de dizaines de milliers

La réponse
Selon la documentation Oracle (citée de 12.1):

Pour un index B-tree, le facteur de regroupement d'index mesure le regroupement physique des lignes par rapport à une valeur d'index.

Le facteur de regroupement d'index aide l'optimiseur à décider si une analyse d'index ou une analyse de table complète est plus efficace pour certaines requêtes). Un facteur de regroupement faible indique un balayage d'index efficace.

Un facteur de regroupement proche du nombre de blocs dans une table indique que les lignes sont physiquement ordonnées dans les blocs de la table par la clé d'index. Si la base de données effectue une analyse complète de la table, la base de données a tendance à récupérer les lignes lorsqu'elles sont stockées sur le disque triées par la clé d'index. Un facteur de regroupement proche du nombre de lignes indique que les lignes sont dispersées de manière aléatoire sur les blocs de base de données par rapport à la clé d'index. Si la base de données effectue une analyse complète de la table, la base de données ne récupérera pas les lignes dans aucun ordre trié par cette clé d'index.

Dans ce cas, les données sont idéalement triées, donc le facteur de regroupement sera égal ou proche du nombre de blocs occupés dans la table. Pour une taille de bloc standard de 8 kilo-octets, vous pouvez vous attendre à ce qu’environ mille valeurs de nombres étroits tiennent dans un bloc, de sorte que le nombre de blocs, et par conséquent le facteur de regroupement, sera de l’ ordre de dizaines .

À quelles valeurs de N le script suivant sera exécuté avec succès dans une base de données standard avec des paramètres standard?


 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

La réponse
Selon la documentation Oracle (citée à partir de 11.2):

Limites de la base de données logique

ObjetType de limiteValeur limite
IndexTaille totale de la colonne indexée75% de la taille du bloc de base de données moins certains frais généraux

Ainsi, la taille totale des colonnes indexées ne doit pas dépasser 6 Ko. Dépend en outre de la base de codage sélectionnée. Pour le codage AL32UTF8, un caractère peut occuper un maximum de 4 octets, donc dans le pire des cas, 6 kilo-octets conviendront à environ 1 500 caractères. Par conséquent, Oracle interdira la création d'index à N = 400 (lorsque la longueur de clé dans le pire des cas est de 1600 caractères * 4 octets + longueur de rowid), tandis qu'à N = 200 (ou moins) , la création d'index fonctionnera sans problème.

L'instruction INSERT avec l'indicateur APPEND est conçue pour charger des données en mode direct. Que se passe-t-il s'il est appliqué à la table sur laquelle le déclencheur est suspendu?


  • Les données seront chargées en mode direct, le déclencheur fonctionnera comme il se doit
  • Les données seront chargées en mode direct, mais le déclencheur ne sera pas exécuté
  • Les données seront chargées en mode conventionnel, le déclencheur fonctionnera comme il se doit
  • Les données seront chargées en mode conventionnel, mais le déclencheur ne sera pas exécuté
  • Les données ne seront pas téléchargées, l'erreur sera corrigée

La réponse
En principe, c'est plus une question de logique. Pour trouver la bonne réponse, je suggère le modèle de raisonnement suivant:

  1. L'insertion en mode direct est effectuée par la formation directe d'un bloc de données, passé le moteur SQL, ce qui garantit une vitesse élevée. Ainsi, assurer l'exécution du déclencheur est très difficile, si possible, et cela n'a aucun sens, car cela ralentira de toute façon considérablement l'insertion.
  2. Le non-déclenchement entraînera le fait que, avec les mêmes données dans la table, l'état de la base de données dans son ensemble (des autres tables) dépendra du mode dans lequel les données sont insérées. Cela détruira évidemment l'intégrité des données et ne peut pas être appliqué comme solution en production.
  3. L'incapacité à effectuer l'opération demandée est généralement traitée comme une erreur. Mais ici, il faut se rappeler que APPEND est un indice, et la logique générale des indices est qu'ils sont pris en compte si possible, sinon, l'opérateur est exécuté sans tenir compte de l'indice.

Ainsi, la réponse attendue est que les données seront chargées en mode normal (SQL), le déclencheur se déclenchera.

Selon la documentation Oracle (citée de 8.04):

Les violations des restrictions entraîneront l'exécution de l'instruction en série, en utilisant le chemin d'insertion conventionnel, sans avertissement ni message d'erreur. Une exception est la restriction des instructions accédant à la même table plusieurs fois dans une transaction, ce qui peut provoquer des messages d'erreur.
Par exemple, si des déclencheurs ou l'intégrité référentielle sont présents sur la table, le conseil APPEND sera ignoré lorsque vous essayez d'utiliser INSERT à chargement direct (série ou parallèle), ainsi que le conseil ou la clause PARALLEL, le cas échéant.

Que se passe-t-il lors de l'exécution du script suivant?


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

  • Exécution réussie
  • Échec de l'erreur de syntaxe
  • Erreur de transaction hors ligne non valide
  • Erreur liée au dépassement de l'imbrication d'appel maximale
  • Erreur de violation de clé étrangère
  • Erreur de verrouillage

La réponse
La table et le déclencheur sont créés correctement et cette opération ne devrait pas entraîner de problèmes. Les transactions autonomes dans le déclencheur sont également autorisées, sinon il serait impossible, par exemple, la journalisation.

Après avoir inséré la première ligne, un déclencheur réussi entraînerait l'insertion de la deuxième ligne, dans le cadre de laquelle le déclencheur fonctionnerait à nouveau, insérer la troisième ligne, et ainsi de suite jusqu'à ce que l'instruction tombe en raison du dépassement de l'imbrication maximale des appels. Cependant, un autre point subtil est déclenché. Au moment où le déclencheur est exécuté, la validation n'est pas encore exécutée pour le premier enregistrement inséré. Par conséquent, un déclencheur fonctionnant dans une transaction autonome tente d'insérer une ligne dans la table qui fait référence par une clé étrangère à un enregistrement qui n'a pas encore été validé. Cela conduit à une attente (une transaction autonome attend que le commit principal comprenne s'il est possible d'insérer des données) et en même temps la transaction principale attend que le commit autonome continue de fonctionner après le déclencheur. Un blocage se produit et, par conséquent, une transaction autonome est renvoyée pour la raison associée aux verrous .

Source: https://habr.com/ru/post/fr459680/


All Articles