Highload++ Siberia 2019'un izinden giderek - Oracle'da 8 görev

Merhaba!

24-25 Haziran tarihlerinde Novosibirsk'te Highload++ Sibirya 2019 konferansı düzenlendi, arkadaşlarımız da oradaydı. rapor “Oracle konteyner veritabanları (CDB/PDB) ve bunların yazılım geliştirmede pratik kullanımı” konusunun metin versiyonunu biraz sonra yayınlayacağız. Çok güzeldi, teşekkürler olegbunin Organizasyona ve gelen herkese teşekkür ederiz.

Highload++ Siberia 2019'un izinden giderek - Oracle'da 8 görev
Oracle bilginizi test edebilmeniz için bu yazımızda standımızda yaşadığımız sorunları sizlerle paylaşmak istiyoruz. Kesimin altında 8 problem, cevap seçenekleri ve açıklamalar bulunmaktadır.

Aşağıdaki script'in çalıştırılması sonucunda göreceğimiz maksimum sıra değeri nedir?

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
  • Hayır bir hata olacak

CevapOracle belgelerine göre (8.1.6'dan alıntı):
Tek bir SQL ifadesinde Oracle, diziyi satır başına yalnızca bir kez artıracaktır. Bir ifade, bir dizi için NEXTVAL'e birden fazla referans içeriyorsa, Oracle diziyi bir kez artırır ve NEXTVAL'in tüm oluşumları için aynı değeri döndürür. Bir ifade hem CURRVAL hem de NEXTVAL'e referanslar içeriyorsa, Oracle diziyi artırır ve ifade içindeki sıralarına bakılmaksızın hem CURRVAL hem de NEXTVAL için aynı değeri döndürür.

Bu durumda, maksimum değer satır sayısına karşılık gelecektir, yani 5.

Aşağıdaki betiğin çalıştırılması sonucunda tabloda kaç satır olacaktır?

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

CevapOracle belgelerine göre (11.2'dan alıntı):

Herhangi bir SQL ifadesini çalıştırmadan önce, Oracle örtülü bir kayıt noktasını işaretler (sizin için mevcut değildir). Daha sonra, ifade başarısız olursa, Oracle onu otomatik olarak geri alır ve geçerli hata kodunu SQLCA'daki SQLCODE'a döndürür. Örneğin, bir INSERT ifadesi benzersiz bir dizine yinelenen bir değer eklemeye çalışarak hataya neden olursa, ifade geri alınır.

HP'nin istemciden aranması da tek bir bildirim olarak kabul edilir ve işlenir. Böylece, üç kayıt eklenerek ilk HP çağrısı başarıyla tamamlanır; ikinci HP çağrısı bir hatayla sonlanıyor ve eklemeyi başardığı dördüncü kaydı geri alıyor; üçüncü çağrı başarısız olur, ve tabloda üç kayıt var.

Aşağıdaki betiğin çalıştırılması sonucunda tabloda kaç satır olacaktır?

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

CevapOracle belgelerine göre (11.2'dan alıntı):

Kontrol kısıtlaması, tablodaki her satırın karşılaması gereken bir koşulu belirtmenize olanak tanır. Kısıtlamayı karşılamak için tablodaki her satır, koşulu TRUE veya bilinmiyor (boş değer nedeniyle) yapmalıdır. Oracle, belirli bir satır için bir kontrol kısıtlaması koşulunu değerlendirdiğinde, koşuldaki herhangi bir sütun adı, o satırdaki sütun değerlerine atıfta bulunur.

Böylece, null değeri kontrolü geçecek ve anonim blok, 3 değeri girilmeye çalışılana kadar başarılı bir şekilde yürütülecektir. Bundan sonra, hata işleme bloğu istisnayı temizleyecek, geri dönüş gerçekleşmeyecek ve tabloda dört satır kalacak 1, null, 2 ve yine null değerleriyle.

Hangi değer çiftleri blokta aynı miktarda yer kaplayacak?

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 ve X
  • B ve Y
  • C ve K
  • C ve Z
  • K ve Z
  • ben ve J
  • J ve X
  • Tüm listelendi

CevapOracle'da çeşitli veri türlerinin depolanmasına ilişkin belgelerden (12.1.0.2) alıntılar burada bulunmaktadır.

CHAR Veri Türü
CHAR veri türü, veritabanı karakter setinde sabit uzunlukta bir karakter dizisi belirtir. Veritabanınızı oluştururken veritabanı karakter kümesini belirtirsiniz. Oracle, bir CHAR sütununda saklanan tüm değerlerin, seçilen uzunluk semantiğinde boyuta göre belirtilen uzunluğa sahip olmasını sağlar. Sütun uzunluğundan daha kısa bir değer girerseniz Oracle, değeri sütun uzunluğuna kadar boş doldurur.

VARCHAR2 Veri Türü
VARCHAR2 veri türü, veritabanı karakter setinde değişken uzunlukta bir karakter dizisi belirtir. Veritabanınızı oluştururken veritabanı karakter kümesini belirtirsiniz. Oracle, bir karakter değerini VARCHAR2 sütununda, değerin sütun uzunluğunu aşmaması koşuluyla, herhangi bir boşluk doldurma olmadan, tam olarak belirttiğiniz şekilde saklar.

NUMBER Veri Türü
NUMBER veri türü, sıfırın yanı sıra 1.0 x 10-130 ila 1.0 x 10126 arasında mutlak değerlere sahip pozitif ve negatif sabit sayıları saklar. Değeri mutlak değeri şuna eşit veya bundan büyük olan bir aritmetik ifade belirtirseniz 1.0 x 10126, ardından Oracle bir hata döndürüyor. Her NUMBER değeri 1 ila 22 bayt gerektirir. Bunu dikkate alarak, belirli bir sayısal veri değeri NUMBER(p) için bayt cinsinden sütun boyutu (burada p, belirli bir değerin kesinliğidir), aşağıdaki formül kullanılarak hesaplanabilir: YUVARLAK((uzunluk(p)+s)/2))+1 burada sayı pozitifse s sıfıra, sayı negatifse s 1'e eşittir.

Ayrıca Null değerlerin saklanması ile ilgili dokümantasyondan bir alıntı yapalım.

Boş, bir sütunda bir değerin olmamasıdır. Boş değerler eksik, bilinmeyen veya uygulanamaz verileri gösterir. Boş değerler, veri değerlerine sahip sütunların arasına düşerse veritabanında saklanır. Bu durumlarda, sütunun uzunluğunu (sıfır) depolamak için 1 bayta ihtiyaç duyarlar. Yeni bir satır başlığı önceki satırda kalan sütunların boş olduğunu işaret ettiğinden, bir satırdaki sondaki boş değerler depolama gerektirmez. Örneğin, bir tablonun son üç sütunu boşsa bu sütunlar için hiçbir veri saklanmaz.

Bu verilere dayanarak mantık yürütüyoruz. Veritabanının AL32UTF8 kodlamasını kullandığını varsayıyoruz. Bu kodlamada Rusça harfler 2 byte yer kaplayacak.

1) A ve X, a 'Y' alanının değeri 1 byte, x 'D' alanının değeri 2 byte alır
2) B ve Y, b'deki 'Vasya' değeri 10 karaktere kadar boşluklarla doldurulacak ve 14 bayt alacaktır, d'deki 'Vasya' 8 bayt alacaktır.
3) C ve K. Her iki alan da NULL değerine sahiptir, onlardan sonra önemli alanlar vardır, dolayısıyla 1 bayt kaplarlar.
4) C ve Z. Her iki alan da NULL değerine sahiptir, ancak Z alanı tablodaki sonuncudur, dolayısıyla yer kaplamaz (0 bayt). C alanı 1 byte yer kaplar.
5) K ve Z. Önceki duruma benzer. K alanındaki değer Z – 1'da 0 byte yer kaplar.
6) I ve J. Dokümantasyona göre her iki değer de 2 byte alacaktır. Uzunluğu belgelerden alınan formülü kullanarak hesaplıyoruz: round( (1 + 0)/2) +1 = 1 + 1 = 2.
7) J ve X. J alanındaki değer 2 byte, X alanındaki değer ise 2 byte alacaktır.

Toplamda doğru seçenekler şunlardır: C ve K, I ve J, J ve X.

T_I indeksinin kümelenme faktörü yaklaşık olarak ne olacaktır?

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

  • Yaklaşık onlarca
  • Yaklaşık yüzlerce
  • Yaklaşık binlerce
  • Yaklaşık onbinlerce

CevapOracle belgelerine göre (12.1'dan alıntı):

Bir B ağacı indeksi için indeks kümeleme faktörü, bir indeks değerine göre satırların fiziksel gruplamasını ölçer.

Dizin kümeleme faktörü, optimize edicinin belirli sorgular için dizin taramasının mı yoksa tam tablo taramasının mı daha verimli olduğuna karar vermesine yardımcı olur). Düşük kümeleme faktörü, verimli bir dizin taramasına işaret eder.

Bir tablodaki blok sayısına yakın bir kümeleme faktörü, tablo bloklarındaki satırların indeks anahtarına göre fiziksel olarak sıralandığını gösterir. Veritabanı tam tablo taraması gerçekleştirirse, veritabanı, dizin anahtarına göre sıralanmış olarak diskte depolanan satırları alma eğilimindedir. Satır sayısına yakın bir kümeleme faktörü, satırların indeks anahtarına göre veritabanı blokları boyunca rastgele dağıldığını gösterir. Veritabanı tam tablo taraması gerçekleştirirse, veritabanı bu dizin anahtarına göre satırları herhangi bir sıralı şekilde almaz.

Bu durumda veriler ideal şekilde sıralanır, böylece kümeleme faktörü tablodaki dolu blokların sayısına eşit veya ona yakın olacaktır. 8 kilobaytlık standart bir blok boyutu için, yaklaşık bin dar sayı değerinin bir bloğa sığmasını bekleyebilirsiniz, dolayısıyla blok sayısı ve sonuç olarak kümeleme faktörü şöyle olacaktır: yaklaşık onlarca.

Aşağıdaki script, standart ayarlara sahip normal bir veritabanında hangi N değerlerinde başarıyla yürütülecektir?

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

CevapOracle belgelerine göre (11.2'dan alıntı):

Mantıksal Veritabanı Sınırları

+
Limit Türü
Sınır Değeri

Dizinler
Dizine eklenen sütunun toplam boyutu
Veritabanı blok boyutunun %75'i eksi bir miktar ek yük

Bu nedenle indekslenen sütunların toplam boyutu 6Kb'ı geçmemelidir. Bundan sonra ne olacağı seçilen temel kodlamaya bağlıdır. AL32UTF8 kodlaması için bir karakter maksimum 4 bayt kaplayabilir, yani en kötü senaryoda 6 kilobayta yaklaşık 1500 karakter sığacaktır. Bu nedenle Oracle, N = 400'de (en kötü durum anahtar uzunluğu 1600 karakter * 4 bayt + satır kimliği uzunluğu olduğunda) dizin oluşturulmasına izin vermeyecektir; N = 200'de (veya daha az) indeks oluşturmak sorunsuz çalışacaktır.

APPEND ipucuna sahip INSERT operatörü, verileri doğrudan modda yüklemek için tasarlanmıştır. Tetikleyicinin asılı olduğu tabloya uygulanırsa ne olur?

  • Veriler doğrudan modda yüklenecek, tetikleyici beklendiği gibi çalışacak
  • Veriler doğrudan modda yüklenecek ancak tetikleyici yürütülmeyecek
  • Veriler geleneksel modda yüklenecek, tetikleyici olması gerektiği gibi çalışacak
  • Veriler geleneksel modda yüklenecek ancak tetikleyici yürütülmeyecek
  • Veriler yüklenmeyecek, bir hata kaydedilecek

CevapTemelde bu daha çok bir mantık meselesidir. Doğru cevabı bulmak için aşağıdaki akıl yürütme modelini öneriyorum:

  1. Doğrudan modda ekleme, yüksek hız sağlayan SQL motorunu atlayarak bir veri bloğunun doğrudan oluşturulmasıyla gerçekleştirilir. Bu nedenle, tetikleyicinin yürütülmesini sağlamak imkansız olmasa da çok zordur ve bunun hiçbir anlamı yoktur, çünkü yine de yerleştirmeyi radikal bir şekilde yavaşlatacaktır.
  2. Tetikleyicinin yürütülmemesi, tablodaki veriler aynıysa, bir bütün olarak veritabanının durumunun (diğer tablolar) bu verilerin eklendiği moda bağlı olacağı gerçeğine yol açacaktır. Bu açıkça veri bütünlüğünü bozacaktır ve üretimde bir çözüm olarak uygulanamaz.
  3. İstenilen işlemin gerçekleştirilememesi genellikle bir hata olarak değerlendirilir. Ancak burada şunu unutmamalıyız ki APPEND bir ipucudur ve ipuçlarının genel mantığı mümkünse dikkate alınması, mümkün değilse ipucu dikkate alınmadan operatörün çalıştırılmasıdır.

Yani beklenen cevap veriler normal (SQL) modda yüklenecek ve tetikleyici etkinleşecektir.

Oracle belgelerine göre (8.04'dan alıntı):

Kısıtlamaların ihlal edilmesi, ifadenin, uyarılar veya hata mesajları olmadan, geleneksel ekleme yolunu kullanarak seri olarak yürütülmesine neden olur. Bir istisna, bir işlemde aynı tabloya birden fazla kez erişen ifadelerin kısıtlanmasıdır; bu, hata mesajlarına neden olabilir.
Örneğin, tabloda tetikleyiciler veya referans bütünlüğü mevcutsa, doğrudan yüklemeli INSERT (seri veya paralel) ve varsa PARALEL ipucu veya yan tümcesini kullanmaya çalıştığınızda APPEND ipucu yok sayılacaktır.

Aşağıdaki komut dosyası çalıştırıldığında ne olacak?

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

  • Başarılı tamamlama
  • Sözdizimi hatası nedeniyle hata
  • Hata: Otonom İşlem Geçerli Değil
  • Maksimum çağrı yerleştirme sınırının aşılmasıyla ilgili hata
  • Yabancı Anahtar İhlali Hatası
  • Kilitlerle ilgili hata

CevapTablo ve tetikleyici oldukça doğru oluşturulmuş ve bu işlemin sorunlara yol açmaması gerekiyor. Bir tetikleyicideki otonom işlemlere de izin verilir, aksi takdirde örneğin günlüğe kaydetme mümkün olmaz.

İlk satırın eklenmesinden sonra başarılı bir tetikleyici tetikleme, ikinci satırın eklenmesine neden olur ve tetikleyicinin yeniden tetiklenmesine, üçüncü bir satırın eklenmesine neden olur ve çağrıların maksimum iç içe geçme sayısının aşılması nedeniyle ifade başarısız olana kadar bu şekilde devam eder. Ancak bir ince nokta daha devreye giriyor. Tetikleyicinin çalıştırıldığı sırada, eklenen ilk kayıt için kayıt henüz tamamlanmamıştır. Bu nedenle, otonom bir işlemde çalışan bir tetikleyici, henüz işlenmemiş bir kayda yabancı anahtara referans veren bir satırı tabloya eklemeye çalışır. Bu, bir beklemeyle sonuçlanır (otonom işlem, ana işlemin veri ekleyip ekleyemeyeceğini görmek için taahhütte bulunmasını bekler) ve aynı zamanda ana işlem, tetiklemeden sonra otonom işlemin çalışmaya devam etmesini bekler. Kilitlenme meydana gelir ve bunun sonucunda otonom işlem, kilitlerden kaynaklanan nedenlerden dolayı iptal edilir..

Ankete sadece kayıtlı kullanıcılar katılabilir. Giriş yapLütfen.

Zor muydu?

  • İki parmak gibi hemen her şeye doğru karar verdim.

  • Pek değil, birkaç soruda yanılmışım.

  • Yarısını doğru çözdüm.

  • Cevabı iki kez tahmin ettim!

  • yorumlara yazacağım

14 kullanıcı oy kullandı. 10 kişi çekimser kaldı.

Kaynak: habr.com

Yorum ekle