دنبال کردن راه های Highload++ Siberia 2019 - 8 کار در اوراکل

سلام!

در 24 تا 25 ژوئن، کنفرانس Highload++ Siberia 2019 در نووسیبیرسک برگزار شد. بچه های ما نیز آنجا بودند. گزارش «پایگاه‌های اطلاعاتی کانتینر اوراکل (CDB/PDB) و کاربرد عملی آنها برای توسعه نرم‌افزار»، نسخه متنی آن را کمی بعد منتشر خواهیم کرد. باحال بود ممنون اولگبونین برای سازمان و همچنین برای همه کسانی که آمدند.

دنبال کردن راه های Highload++ Siberia 2019 - 8 کار در اوراکل
در این پست می خواهیم مشکلاتی را که در غرفه خود داشتیم با شما در میان بگذاریم تا دانش اوراکل خود را محک بزنید. در زیر برش 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
  • نه، خطایی رخ خواهد داد

پاسخطبق اسناد اوراکل (به نقل از 8.1.6):
در یک دستور SQL، Oracle دنباله را تنها یک بار در هر سطر افزایش می‌دهد. اگر یک دستور حاوی بیش از یک مرجع به NEXTVAL برای یک دنباله باشد، اوراکل دنباله را یک بار افزایش می دهد و همان مقدار را برای همه موارد 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

پاسخطبق اسناد اوراکل (به نقل از 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

پاسخطبق اسناد اوراکل (به نقل از 11.2):

یک محدودیت چک به شما امکان می دهد شرایطی را مشخص کنید که هر ردیف در جدول باید آن را برآورده کند. برای ارضای محدودیت، هر ردیف در جدول باید شرط را درست یا ناشناخته (به دلیل تهی) کند. وقتی اوراکل یک شرط محدودیت چک را برای یک ردیف خاص ارزیابی می‌کند، نام ستون‌ها در این شرط به مقادیر ستون در آن سطر اشاره می‌کند.

بنابراین، مقدار 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, 'Д', 'Вася');

  • A و X
  • B و Y
  • C و K
  • C و Z
  • K و Z
  • من و جی
  • J و X
  • همه ذکر شده

پاسخدر اینجا گزیده هایی از مستندات (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 برابر با صفر و در صورت منفی بودن عدد s برابر با 1 است.

علاوه بر این، بیایید گزیده ای از مستندات مربوط به ذخیره مقادیر Null بگیریم.

null عدم وجود مقدار در یک ستون است. Null ها نشان دهنده داده های گم شده، ناشناخته یا غیرقابل اجرا هستند. تهی ها اگر بین ستون هایی با مقادیر داده قرار گیرند در پایگاه داده ذخیره می شوند. در این موارد برای ذخیره طول ستون (صفر) به 1 بایت نیاز دارند. تهی های دنباله دار در یک ردیف نیازی به ذخیره سازی ندارند زیرا سرصفحه سطر جدید نشان می دهد که ستون های باقی مانده در ردیف قبلی خالی هستند. به عنوان مثال، اگر سه ستون آخر یک جدول خالی باشد، هیچ داده ای برای این ستون ها ذخیره نمی شود.

بر اساس این داده ها، ما استدلال می سازیم. ما فرض می کنیم که پایگاه داده از رمزگذاری AL32UTF8 استفاده می کند. در این رمزگذاری، حروف روسی 2 بایت را اشغال خواهند کرد.

1) A و X، مقدار فیلد a 'Y' 1 بایت می گیرد، مقدار فیلد x 'D' 2 بایت می گیرد.
2) B و Y، 'Vasya' در b مقدار با فاصله تا 10 کاراکتر پر می شود و 14 بایت می گیرد، 'Vasya' در d 8 بایت می گیرد.
3) C و K. هر دو فیلد دارای مقدار NULL هستند، پس از آنها فیلدهای قابل توجهی وجود دارد، بنابراین آنها 1 بایت را اشغال می کنند.
4) C و Z. هر دو فیلد دارای مقدار NULL هستند، اما فیلد Z آخرین قسمت جدول است، بنابراین فضای (0 بایت) را اشغال نمی کند. فیلد C 1 بایت را اشغال می کند.
5) ک و ض مشابه مورد قبل. مقدار در فیلد K 1 بایت را اشغال می کند، در Z – 0.
6) I و J. طبق مستندات، هر دو مقدار 2 بایت می گیرند. ما طول را با استفاده از فرمول برگرفته از مستندات محاسبه می کنیم: دور( (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);

  • حدود ده ها
  • حدود صدها
  • حدود هزاران
  • حدود ده ها هزار

پاسخطبق اسناد اوراکل (به نقل از 12.1):

برای شاخص B-tree، عامل خوشه‌بندی شاخص، گروه‌بندی فیزیکی ردیف‌ها را در رابطه با مقدار شاخص اندازه‌گیری می‌کند.

عامل خوشه‌بندی شاخص به بهینه‌ساز کمک می‌کند تا تصمیم بگیرد که آیا اسکن فهرست یا اسکن جدول کامل برای پرس و جوهای خاص کارآمدتر است. ضریب خوشه بندی کم نشان دهنده یک اسکن شاخص کارآمد است.

یک عامل خوشه‌بندی که نزدیک به تعداد بلوک‌های یک جدول است، نشان می‌دهد که ردیف‌ها از نظر فیزیکی در بلوک‌های جدول توسط کلید شاخص مرتب شده‌اند. اگر پایگاه داده یک اسکن کامل جدول را انجام دهد، پایگاه داده تمایل دارد تا ردیف‌ها را همانطور که بر روی دیسک ذخیره می‌شوند، مرتب‌سازی شده توسط کلید فهرست بازیابی کند. یک عامل خوشه‌بندی که نزدیک به تعداد ردیف‌ها است، نشان می‌دهد که ردیف‌ها به‌طور تصادفی در بلوک‌های پایگاه داده در رابطه با کلید فهرست پراکنده شده‌اند. اگر پایگاه داده اسکن کامل جدول را انجام دهد، پایگاه داده سطرها را به ترتیب مرتب شده با این کلید فهرست بازیابی نمی کند.

در این حالت، داده ها به طور ایده آل مرتب شده اند، بنابراین ضریب خوشه بندی برابر یا نزدیک به تعداد بلوک های اشغال شده در جدول خواهد بود. برای اندازه بلوک استاندارد 8 کیلوبایتی، می توان انتظار داشت که حدود هزار عدد باریک در یک بلوک قرار گیرد، بنابراین تعداد بلوک ها و در نتیجه ضریب خوشه بندی خواهد بود. حدود ده ها.

اسکریپت زیر با چه مقادیر 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

پاسخطبق اسناد اوراکل (به نقل از 11.2):

محدودیت های منطقی پایگاه داده

مورد
نوع محدودیت
مقدار محدود

شاخص
اندازه کل ستون نمایه شده
75 درصد از اندازه بلوک پایگاه داده منهای مقداری سربار

بنابراین، اندازه کل ستون های نمایه شده نباید از 6 کیلوبایت تجاوز کند. آنچه بعدا اتفاق می افتد بستگی به کدگذاری پایه انتخاب شده دارد. برای رمزگذاری AL32UTF8، یک کاراکتر می تواند حداکثر 4 بایت را اشغال کند، بنابراین در بدترین حالت، حدود 6 کاراکتر در 1500 کیلوبایت جا می شود. بنابراین، اوراکل ایجاد ایندکس را در N = 400 (زمانی که طول کلید در بدترین حالت 1600 کاراکتر * 4 بایت + طول ردیف باشد) مجاز نمی‌داند. در N = 200 (یا کمتر) ایجاد ایندکس بدون مشکل کار خواهد کرد.

عملگر INSERT با اشاره APPEND برای بارگیری داده ها در حالت مستقیم طراحی شده است. اگر روی میزی که ماشه روی آن آویزان است اعمال شود چه اتفاقی می افتد؟

  • داده ها در حالت مستقیم بارگیری می شوند، ماشه همانطور که انتظار می رود کار خواهد کرد
  • داده ها در حالت مستقیم بارگیری می شوند، اما ماشه اجرا نمی شود
  • داده ها در حالت معمولی بارگیری می شوند، ماشه همانطور که باید کار می کند
  • داده ها در حالت معمولی بارگیری می شوند، اما ماشه اجرا نمی شود
  • داده ها بارگیری نمی شوند، یک خطا ثبت می شود

پاسخاساساً این بیشتر یک بحث منطقی است. برای یافتن پاسخ صحیح، مدل استدلال زیر را پیشنهاد می کنم:

  1. درج در حالت مستقیم با تشکیل مستقیم یک بلوک داده، دور زدن موتور SQL انجام می شود که سرعت بالا را تضمین می کند. بنابراین، اطمینان از اجرای ماشه بسیار دشوار است، اگر نگوییم غیرممکن، و هیچ فایده ای در این کار وجود ندارد، زیرا همچنان سرعت درج را به شدت کاهش می دهد.
  2. عدم اجرای ماشه منجر به این واقعیت می شود که اگر داده های جدول یکسان باشد، وضعیت پایگاه داده به عنوان یک کل (جدول های دیگر) به حالتی که این داده ها در آن درج شده است بستگی دارد. این بدیهی است که یکپارچگی داده ها را از بین می برد و نمی تواند به عنوان یک راه حل در تولید استفاده شود.
  3. ناتوانی در انجام عملیات درخواستی به طور کلی به عنوان یک خطا تلقی می شود. اما در اینجا باید به یاد داشته باشیم که APPEND یک اشاره است و منطق کلی نکات این است که در صورت امکان به آنها توجه می شود، اما اگر نه، عملگر بدون در نظر گرفتن اشاره اجرا می شود.

بنابراین پاسخ مورد انتظار است داده ها در حالت عادی (SQL) بارگذاری می شوند، ماشه فعال می شود.

طبق اسناد اوراکل (به نقل از 8.04):

نقض محدودیت‌ها باعث می‌شود دستور به صورت سریالی، با استفاده از مسیر درج معمولی، بدون اخطار یا پیام خطا اجرا شود. یک استثنا، محدودیتی است که در بیانیه‌ها بیش از یک بار در یک تراکنش به یک جدول دسترسی دارند، که می‌تواند باعث ایجاد پیام‌های خطا شود.
برای مثال، اگر تریگرها یا یکپارچگی ارجاعی روی جدول وجود داشته باشد، وقتی می‌خواهید از INSERT بارگذاری مستقیم (سریال یا موازی)، و همچنین اشاره یا بند PARALLEL در صورت وجود استفاده کنید، راهنمایی APPEND نادیده گرفته می‌شود.

وقتی اسکریپت زیر اجرا شود چه اتفاقی می افتد؟

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

  • اجرای موفقیت آمیز
  • خرابی به دلیل خطای نحوی
  • خطا: تراکنش مستقل معتبر نیست
  • خطای مربوط به فراتر رفتن از حداکثر تودرتوی تماس
  • خطای نقض کلید خارجی
  • خطای مربوط به قفل

پاسخجدول و ماشه کاملا درست ایجاد شده اند و این عملیات نباید منجر به مشکل شود. تراکنش های مستقل در یک ماشه نیز مجاز هستند، در غیر این صورت، برای مثال، ثبت نام امکان پذیر نخواهد بود.

پس از درج ردیف اول، شلیک موفقیت آمیز ماشه باعث درج ردیف دوم می شود و باعث می شود که ماشه دوباره شلیک شود، ردیف سوم وارد شود و به همین ترتیب تا زمانی که عبارت به دلیل بیش از حداکثر تودرتوی تماس ها شکست بخورد. با این حال، یک نکته ظریف دیگر در بازی وجود دارد. در زمانی که تریگر اجرا می شود، commit برای اولین رکورد درج شده هنوز کامل نشده است. بنابراین، یک تریگر که در یک تراکنش مستقل اجرا می‌شود، سعی می‌کند ردیفی را در جدول وارد کند که یک کلید خارجی را به رکوردی ارجاع می‌دهد که هنوز انجام نشده است. این منجر به یک انتظار می شود (تراکنش مستقل منتظر می ماند تا تراکنش اصلی متعهد شود تا ببیند آیا می تواند داده ها را وارد کند) و در همان زمان تراکنش اصلی منتظر می ماند تا تراکنش مستقل پس از تریگر به کار خود ادامه دهد. یک بن بست رخ می دهد و در نتیجه تراکنش مستقل به دلایل مربوط به قفل لغو می شود..

فقط کاربران ثبت نام شده می توانند در نظرسنجی شرکت کنند. ورود، لطفا.

سخت بود؟

  • مثل دو انگشت، بلافاصله همه چیز را درست تصمیم گرفتم.

  • نه واقعا، من در یکی دو سوال اشتباه کردم.

  • نصفش رو درست حل کردم

  • دوبار جواب رو حدس زدم!

  • در نظرات می نویسم

14 کاربر رای دادند. 10 کاربر رای ممتنع دادند.

منبع: www.habr.com

اضافه کردن نظر