Ακολουθώντας τα βήματα του 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):

Ένας περιορισμός ελέγχου σάς επιτρέπει να καθορίσετε μια συνθήκη που πρέπει να ικανοποιεί κάθε γραμμή στον πίνακα. Για να ικανοποιηθεί ο περιορισμός, κάθε γραμμή στον πίνακα πρέπει να κάνει τη συνθήκη είτε TRUE είτε άγνωστη (λόγω μηδενικού). Όταν η Oracle αξιολογεί μια συνθήκη περιορισμού ελέγχου για μια συγκεκριμένη γραμμή, τυχόν ονόματα στηλών στη συνθήκη αναφέρονται στις τιμές στηλών σε αυτήν τη σειρά.

Έτσι, η τιμή null θα περάσει τον έλεγχο και το ανώνυμο μπλοκ θα εκτελεστεί με επιτυχία μέχρι να γίνει προσπάθεια εισαγωγής της τιμής 3. Μετά από αυτό, το μπλοκ διαχείρισης σφαλμάτων θα διαγράψει την εξαίρεση, δεν θα συμβεί επαναφορά και θα μείνουν τέσσερις σειρές στον πίνακα με τιμές 1, null, 2 και πάλι null.

Ποια ζεύγη τιμών θα καταλάβουν τον ίδιο χώρο στο μπλοκ;

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

  • Α και Χ
  • Β και Υ
  • Γ και Κ
  • Γ και Ζ
  • Κ και Ζ
  • Εγώ και ο Τζ
  • J και X
  • Όλα αναφέρονται

ΑπάντησηΑκολουθούν αποσπάσματα από την τεκμηρίωση (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 byte. Λαμβάνοντας αυτό υπόψη, το μέγεθος της στήλης σε byte για μια συγκεκριμένη τιμή αριθμητικών δεδομένων NUMBER(p), όπου p είναι η ακρίβεια μιας δεδομένης τιμής, μπορεί να υπολογιστεί χρησιμοποιώντας τον ακόλουθο τύπο: ROUND((μήκος(p)+s)/2))+1 όπου s ισούται με μηδέν εάν ο αριθμός είναι θετικός και s ίσο με 1 εάν ο αριθμός είναι αρνητικός.

Επιπλέον, ας πάρουμε ένα απόσπασμα από την τεκμηρίωση σχετικά με την αποθήκευση τιμών Null.

Το null είναι η απουσία τιμής σε μια στήλη. Τα μηδενικά δηλώνουν δεδομένα που λείπουν, άγνωστα ή δεν εφαρμόζονται. Τα μηδενικά αποθηκεύονται στη βάση δεδομένων εάν εμπίπτουν μεταξύ στηλών με τιμές δεδομένων. Σε αυτές τις περιπτώσεις, απαιτούν 1 byte για να αποθηκεύσουν το μήκος της στήλης (μηδέν). Τα τελικά μηδενικά σε μια γραμμή δεν απαιτούν αποθήκευση, επειδή μια νέα κεφαλίδα γραμμής σηματοδοτεί ότι οι υπόλοιπες στήλες στην προηγούμενη σειρά είναι μηδενικές. Για παράδειγμα, εάν οι τρεις τελευταίες στήλες ενός πίνακα είναι μηδενικές, τότε δεν αποθηκεύονται δεδομένα για αυτές τις στήλες.

Με βάση αυτά τα δεδομένα, χτίζουμε συλλογισμούς. Υποθέτουμε ότι η βάση δεδομένων χρησιμοποιεί κωδικοποίηση AL32UTF8. Σε αυτήν την κωδικοποίηση, τα ρωσικά γράμματα θα καταλαμβάνουν 2 byte.

1) A και X, η τιμή του πεδίου a 'Y' παίρνει 1 byte, η τιμή του πεδίου x 'D' παίρνει 2 byte
2) B και Y, 'Vasya' στο b η τιμή θα συμπληρώνεται με κενά έως 10 χαρακτήρες και θα παίρνει 14 byte, το 'Vasya' στο d θα παίρνει 8 byte.
3) C και K. Και τα δύο πεδία έχουν την τιμή NULL, μετά από αυτά υπάρχουν σημαντικά πεδία, άρα καταλαμβάνουν 1 byte.
4) C και Z. Και τα δύο πεδία έχουν την τιμή NULL, αλλά το πεδίο Z είναι το τελευταίο στον πίνακα, επομένως δεν καταλαμβάνει χώρο (0 byte). Το πεδίο C καταλαμβάνει 1 byte.
5) Κ και Ζ. Παρόμοια με την προηγούμενη περίπτωση. Η τιμή στο πεδίο K καταλαμβάνει 1 byte, σε Z – 0.
6) I και J. Σύμφωνα με την τεκμηρίωση, και οι δύο τιμές θα λάβουν 2 byte. Υπολογίζουμε το μήκος χρησιμοποιώντας τον τύπο που λαμβάνεται από την τεκμηρίωση: round( (1 + 0)/2) +1 = 1 + 1 = 2.
7) J και X. Η τιμή στο πεδίο J θα πάρει 2 byte, η τιμή στο πεδίο X θα πάρει 2 byte.

Συνολικά, οι σωστές επιλογές είναι: 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):

Για έναν δείκτη B-tree, ο παράγοντας ομαδοποίησης δείκτη μετρά τη φυσική ομαδοποίηση των σειρών σε σχέση με μια τιμή ευρετηρίου.

Ο παράγοντας ομαδοποίησης ευρετηρίου βοηθά τον βελτιστοποιητή να αποφασίσει εάν η σάρωση ευρετηρίου ή η σάρωση πλήρους πίνακα είναι πιο αποτελεσματική για ορισμένα ερωτήματα). Ένας χαμηλός συντελεστής ομαδοποίησης υποδηλώνει αποτελεσματική σάρωση ευρετηρίου.

Ένας παράγοντας ομαδοποίησης που είναι κοντά στον αριθμό των μπλοκ σε έναν πίνακα υποδεικνύει ότι οι σειρές ταξινομούνται φυσικά στα μπλοκ του πίνακα από το κλειδί ευρετηρίου. Εάν η βάση δεδομένων πραγματοποιεί πλήρη σάρωση πίνακα, τότε η βάση δεδομένων τείνει να ανακτά τις σειρές καθώς είναι αποθηκευμένες στο δίσκο ταξινομημένες με βάση το κλειδί ευρετηρίου. Ένας παράγοντας ομαδοποίησης που είναι κοντά στον αριθμό των σειρών υποδεικνύει ότι οι σειρές είναι διασκορπισμένες τυχαία στα μπλοκ βάσης δεδομένων σε σχέση με το κλειδί ευρετηρίου. Εάν η βάση δεδομένων εκτελεί πλήρη σάρωση πίνακα, τότε η βάση δεδομένων δεν θα ανακτήσει σειρές με οποιαδήποτε ταξινόμηση κατά αυτό το κλειδί ευρετηρίου.

Σε αυτήν την περίπτωση, τα δεδομένα είναι ιδανικά ταξινομημένα, επομένως ο παράγοντας ομαδοποίησης θα είναι ίσος ή κοντά στον αριθμό των κατειλημμένων μπλοκ στον πίνακα. Για ένα τυπικό μέγεθος μπλοκ 8 kilobyte, μπορείτε να περιμένετε ότι περίπου χίλιες στενές τιμές αριθμού θα χωρέσουν σε ένα μπλοκ, επομένως ο αριθμός των μπλοκ και ως αποτέλεσμα ο παράγοντας ομαδοποίησης θα είναι περίπου δεκάδες.

Σε ποιες τιμές του 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 byte, επομένως στη χειρότερη περίπτωση, περίπου 6 χαρακτήρες θα χωρέσουν σε 1500 kilobyte. Επομένως, η Oracle θα απαγορεύσει τη δημιουργία ευρετηρίου σε N = 400 (όταν το μήκος του κλειδιού στη χειρότερη περίπτωση είναι 1600 χαρακτήρες * 4 byte + μήκος σειράς), ενώ σε 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);

  • Επιτυχής ολοκλήρωση
  • Αποτυχία λόγω συντακτικού σφάλματος
  • Σφάλμα: Η αυτόνομη συναλλαγή δεν είναι έγκυρη
  • Σφάλμα που σχετίζεται με την υπέρβαση της μέγιστης ένθεσης κλήσεων
  • Σφάλμα παραβίασης ξένου κλειδιού
  • Σφάλμα που σχετίζεται με κλειδαριές

ΑπάντησηΟ πίνακας και η σκανδάλη έχουν δημιουργηθεί αρκετά σωστά και αυτή η λειτουργία δεν πρέπει να οδηγήσει σε προβλήματα. Επιτρέπονται επίσης αυτόνομες συναλλαγές σε ένα trigger, διαφορετικά η καταγραφή δεν θα ήταν δυνατή, για παράδειγμα.

Μετά την εισαγωγή της πρώτης σειράς, μια επιτυχής ενεργοποίηση της σκανδάλης θα προκαλούσε την εισαγωγή της δεύτερης σειράς, με αποτέλεσμα η σκανδάλη να ενεργοποιηθεί ξανά, να εισαχθεί μια τρίτη σειρά και ούτω καθεξής έως ότου η δήλωση απέτυχε λόγω υπέρβασης της μέγιστης ένθεσης κλήσεων. Ωστόσο, ένα άλλο λεπτό σημείο μπαίνει στο παιχνίδι. Τη στιγμή που εκτελείται η ενεργοποίηση, η δέσμευση δεν έχει ακόμη ολοκληρωθεί για την πρώτη εισαγόμενη εγγραφή. Επομένως, ένας κανόνας που εκτελείται σε μια αυτόνομη συναλλαγή προσπαθεί να εισαγάγει στον πίνακα μια σειρά που αναφέρεται σε ένα ξένο κλειδί σε μια εγγραφή που δεν έχει ακόμη δεσμευτεί. Αυτό οδηγεί σε αναμονή (η αυτόνομη συναλλαγή περιμένει να δεσμευτεί η κύρια συναλλαγή για να δει αν μπορεί να εισαγάγει δεδομένα) και ταυτόχρονα η κύρια συναλλαγή περιμένει να συνεχίσει να λειτουργεί η αυτόνομη συναλλαγή μετά την ενεργοποίηση. Παρουσιάζεται αδιέξοδο και, ως αποτέλεσμα, η αυτόνομη συναλλαγή ακυρώνεται για λόγους που σχετίζονται με κλειδώματα.

Μόνο εγγεγραμμένοι χρήστες μπορούν να συμμετάσχουν στην έρευνα. Συνδεθείτε, Σας παρακαλούμε.

Ήταν δύσκολο να;

  • Σαν δύο δάχτυλα, αμέσως τα αποφάσισα όλα σωστά.

  • Όχι πραγματικά, έκανα λάθος σε μερικές ερωτήσεις.

  • Το μισό το έλυσα σωστά.

  • Την απάντηση την μάντεψα δύο φορές!

  • Θα γράψω στα σχόλια

Ψήφισαν 14 χρήστες. 10 χρήστες απείχαν.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο