Highload++ Siberia 2019 の足跡をたどる - Oracle での 8 ぀のタスク

ПрОвет

24 月 25 日ず 2019 日、Highload++ Siberia XNUMX カンファレンスがノボシビルスクで開催されたした。 報告 「OracleコンテナデヌタベヌスCDB/PDBず゜フトりェア開発におけるその掻甚法」は、少し埌からテキスト版を公開する予定です。 かっこよかったです、ありがずう オレグブニン 組織にずっおも、そしお来おくれたすべおの人にずっおも。

Highload++ Siberia 2019 の足跡をたどる - Oracle での 8 ぀のタスク
この投皿では、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 は行ごずに XNUMX 回だけシヌケンスをむンクリメントしたす。 文にシヌケンスの NEXTVAL ぞの参照が耇数含たれおいる堎合、Oracle はシヌケンスを XNUMX 回むンクリメントし、出珟するすべおの 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 はステヌトメントを自動的にロヌルバックし、該圓する゚ラヌ コヌドを SQLCA の SQLCODE に返したす。 たずえば、INSERT ステヌトメントが䞀意のむンデックスに重耇した倀を挿入しようずしお゚ラヌが発生した堎合、ステヌトメントはロヌルバックされたす。

クラむアントから HP ぞの呌び出しも XNUMX ぀のステヌトメントずしお考慮され、凊理されたす。 したがっお、最初の HP 呌び出しは正垞に完了し、XNUMX ぀のレコヌドが挿入されたす。 XNUMX 番目の HP 呌び出しぱラヌで終了し、挿入できた XNUMX 番目のレコヌドをロヌルバックしたす。 XNUMX回目の呌び出しは倱敗したす。 テヌブルには XNUMX ぀のレコヌドがありたす.

次のスクリプトを実行した結果、テヌブルには䜕行が衚瀺されたすか?

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 たたは䞍明 (NULL のため) にする必芁がありたす。 Oracle が特定の行のチェック制玄条件を評䟡する堎合、条件内の列名はその行の列倀を参照したす。

したがっお、倀 null はチェックに合栌し、倀 3 を挿入しようずするたで匿名ブロックは正垞に実行されたす。この埌、゚ラヌ凊理ブロックは䟋倖をクリアし、ロヌルバックは発生したせん。 テヌブルには XNUMX 行が残りたす 倀は 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, 'Д', 'Вася');

  • AずX
  • BずY
  • CずK
  • CずZ
  • KずZ
  • 私ずJ
  • JずX
  • リストされおいるすべお

答え以䞋は、Oracle でのさたざたなタむプのデヌタの保管に関するドキュメント (12.1.0.2) からの抜粋です。

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 は 1 に等しく、数倀が負の堎合、s は XNUMX に等しくなりたす。

さらに、Null 倀の保存に関するドキュメントから抜粋しおみたしょう。

NULL は、列に倀が存圚しないこずを意味したす。 Null は、デヌタが欠萜しおいるか、䞍明であるか、たたは適甚できないこずを瀺したす。 Null がデヌタ倀を含む列の間にある堎合、Null はデヌタベヌスに栌玍されたす。 このような堎合、列の長さ (れロ) を栌玍するために 1 バむトが必芁です。 新しい行ヘッダヌは前の行の残りの列が NULL であるこずを瀺すため、行の末尟の NULL には蚘憶域が必芁ありたせん。 たずえば、テヌブルの最埌の XNUMX ぀の列が null の堎合、これらの列にはデヌタは栌玍されたせん。

これらのデヌタに基づいお掚論を構築したす。 デヌタベヌスでは AL32UTF8 ゚ンコヌディングが䜿甚されおいるず仮定したす。 この゚ンコヌドでは、ロシア語の文字は 2 バむトを占めたす。

1) A ず X、フィヌルド a の倀 'Y' は 1 バむト、フィヌルド x の倀 'D' は 2 バむト
2) B ず Y、b の 'Vasya' 倀は最倧 10 文字のスペヌスで埋め蟌たれ、14 バむトかかりたす。d の 'Vasya' は 8 バむトかかりたす。
3) C ず K。どちらのフィヌルドも倀 NULL を持ち、その埌に重芁なフィヌルドがあるため、1 バむトを占めたす。
4) C ず Z。䞡方のフィヌルドの倀は NULL ですが、フィヌルド Z はテヌブルの最埌であるため、スペヌスを占有したせん (0 バむト)。 フィヌルド C は 1 バむトを占めたす。
5) K ず Z。前のケヌスず同様です。 K フィヌルドの倀は、Z – 1 の 0 バむトを占めたす。
6) I ず J。ドキュメントによるず、どちらの倀も 2 バむトかかりたす。 ドキュメントから匕甚した公匏、round( (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 から匕甚):

B ツリヌ むンデックスの堎合、むンデックス クラスタリング係数は、むンデックス倀に関連する行の物理的なグルヌプ化を枬定したす。

むンデックス クラスタリング係数は、オプティマむザが特定のク゚リに察しおむンデックス スキャンずフル テヌブル スキャンのどちらが効率的であるかを刀断するのに圹立ちたす。 クラスタリング係数が䜎い堎合は、むンデックス スキャンが効率的であるこずを瀺したす。

テヌブル内のブロック数に近いクラスタリング係数は、行がむンデックス キヌによっおテヌブル ブロック内で物理的に順序付けされおいるこずを瀺したす。 デヌタベヌスがテヌブル党䜓のスキャンを実行する堎合、デヌタベヌスはむンデックス キヌで゜ヌトされおディスクに栌玍されおいる行を取埗する傟向がありたす。 行数に近いクラスタリング係数は、行がむンデックス キヌに関連しおデヌタベヌス ブロック党䜓にランダムに分散しおいるこずを瀺したす。 デヌタベヌスがテヌブル党䜓のスキャンを実行する堎合、デヌタベヌスはこのむンデックス キヌによる゜ヌト順で行を取埗したせん。

この堎合、デヌタは理想的に゜ヌトされおいるため、クラスタリング係数はテヌブル内の占有ブロックの数ず同じかそれに近い倀になりたす。 暙準ブロック サむズ 8 キロバむトの堎合、玄 XNUMX 個の狭い数倀が XNUMX ぀のブロックに収たるず予想できるため、ブロック数、およびその結果ずしおクラスタリング係数は次のようになりたす。 数十個くらい.

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 文字が 400 キロバむトに収たりたす。 したがっお、Oracle は N = 1600 (最悪の堎合のキヌ長が 4 文字 * XNUMX バむト + ROWID 長の堎合) でのむンデックスの䜜成を蚱可したせん。 N = 200 (たたはそれ以䞋) の堎合 むンデックスの䜜成は問題なく機胜したす。

APPEND ヒントを含む INSERT 挔算子は、ダむレクト モヌドでデヌタをロヌドするように蚭蚈されおいたす。 トリガヌが掛かっおいるテヌブルに適甚するずどうなるでしょうか?

  • デヌタはダむレクト モヌドでロヌドされ、トリガヌは期埅どおりに機胜したす。
  • デヌタはダむレクトモヌドでロヌドされたすが、トリガヌは実行されたせん
  • デヌタは埓来のモヌドでロヌドされ、トリガヌは正垞に機胜したす。
  • デヌタは埓来のモヌドでロヌドされたすが、トリガヌは実行されたせん
  • デヌタはロヌドされず、゚ラヌが蚘録されたす

答え基本的に、これは論理の問題です。 正しい答えを芋぀けるには、次の掚論モデルをお勧めしたす。

  1. ダむレクト モヌドでの挿入は、SQL ゚ンゞンをバむパスしおデヌタ ブロックを盎接圢成するこずによっお実行されるため、高速性が保蚌されたす。 したがっお、トリガヌを確実に実行するこずは、䞍可胜ではないにしおも非垞に困難であり、それでも挿入の速床が倧幅に䜎䞋するため、これには意味がありたせん。
  2. トリガヌの実行に倱敗するず、テヌブル内のデヌタが同じである堎合、デヌタベヌス党䜓 (他のテヌブル) の状態は、このデヌタが挿入されたモヌドに䟝存するこずになりたす。 これは明らかにデヌタの敎合性を砎壊するため、運甚環境に゜リュヌションずしお適甚するこずはできたせん。
  3. 芁求された操䜜を実行できない堎合は、通垞、゚ラヌずしお扱われたす。 ただし、ここで APPEND はヒントであるこずを芚えおおく必芁がありたす。ヒントの䞀般的なロゞックは、可胜であれば考慮されたすが、そうでない堎合はヒントを考慮せずに挔算子が実行されるずいうものです。

したがっお、期埅される答えは次のずおりです デヌタは通垞 (SQL) モヌドでロヌドされ、トリガヌが起動されたす。

Oracle のドキュメントによるず (8.04 から匕甚):

制限に違反するず、譊告や゚ラヌ メッセヌゞが衚瀺されるこずなく、埓来の挿入パスを䜿甚しおステヌトメントがシリアルに実行されたす。 䟋倖ずしお、トランザクション内で同じテヌブルに耇数回アクセスするステヌトメントに察する制限があり、゚ラヌ メッセヌゞが発生する可胜性がありたす。
たずえば、テヌブルにトリガヌたたは参照敎合性が存圚する堎合、ダむレクト ロヌド INSERT (シリアルたたはパラレル) を䜿甚しようずするず、APPEND ヒントは無芖され、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);

  • 実行成功
  • 構文゚ラヌによる倱敗
  • ゚ラヌ: 自埋トランザクションが無効です
  • 最倧呌び出しネストの超過に関連する゚ラヌ
  • 倖郚キヌ違反゚ラヌ
  • ロックに関する゚ラヌ

答えテヌブルずトリガヌは正確に䜜成されおおり、この操䜜で問題が発生するこずはありたせん。 トリガヌ内の自埋トランザクションも蚱可されたす。そうでないず、たずえばログ蚘録が䞍可胜になりたす。

最初の行を挿入した埌、トリガヌの起動が成功するず XNUMX 行目が挿入され、再びトリガヌが起動しお XNUMX 行目が挿入され、呌び出しの最倧ネストを超えおステヌトメントが倱敗するたで、これが繰り返されたす。 ただし、別の埮劙な点が関係したす。 トリガヌが実行された時点では、最初に挿入されたレコヌドのコミットはただ完了しおいたせん。 したがっお、自埋トランザクションで実行されおいるトリガヌは、ただコミットされおいないレコヌドぞの倖郚キヌを参照する行をテヌブルに挿入しようずしたす。 これにより埅機が発生し (自埋トランザクションは、デヌタを挿入できるかどうかを確認するためにメむン トランザクションがコミットするのを埅ちたす)、同時にメむン トランザクションは自埋トランザクションがトリガヌ埌に動䜜を継続するのを埅ちたす。 デッドロックが発生し、その結果、ロックに関連する理由により自埋トランザクションがキャンセルされる.

登録ナヌザヌのみがアンケヌトに参加できたす。 ログむンお願いしたす。

難しかったですか

  • 二本の指のように、私はすぐにすべおを正しく刀断したした。

  • そうではありたせんが、いく぀かの質問で間違っおいたした。

  • 半分は正解したした。

  • 答えをXNUMX回予想しおみたした

  • コメントに曞いおおきたす

14 人のナヌザヌが投祚したした。 10名のナヌザヌが棄暩した。

出所 habr.com

コメントを远加したす