ตามรอย Highload++ Siberia 2019 - 8 งานบน Oracle

Hi!

ในวันที่ 24-25 มิถุนายน การประชุม Highload++ Siberia 2019 จัดขึ้นที่เมือง Novosibirsk เพื่อนของเราก็อยู่ที่นั่นด้วย รายงาน “ฐานข้อมูลคอนเทนเนอร์ 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, 'Д', 'Вася');

  • เอ และ เอ็กซ์
  • บีและวาย
  • ซี และ เค
  • ซี และ ซี
  • เค และ ซี
  • ฉันและเจ
  • เจ และ เอ็กซ์
  • รายการทั้งหมด

ตอบต่อไปนี้เป็นข้อความที่ตัดตอนมาจากเอกสารประกอบ (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 ไบต์ เมื่อคำนึงถึงสิ่งนี้ ขนาดคอลัมน์เป็นไบต์สำหรับค่าข้อมูลตัวเลขเฉพาะ NUMBER(p) โดยที่ p คือความแม่นยำของค่าที่กำหนด สามารถคำนวณได้โดยใช้สูตรต่อไปนี้: รอบ((ความยาว(p)+s)/2))+1 โดยที่ s เท่ากับศูนย์หากตัวเลขเป็นบวก และ s เท่ากับ 1 หากตัวเลขเป็นลบ

นอกจากนี้ เรามาตัดตอนมาจากเอกสารประกอบเกี่ยวกับการจัดเก็บค่า Null

ค่าว่างคือการไม่มีค่าในคอลัมน์ ค่า Null หมายถึงข้อมูลสูญหาย ไม่ทราบ หรือใช้งานไม่ได้ ค่า Null จะถูกจัดเก็บไว้ในฐานข้อมูลหากค่าว่างอยู่ระหว่างคอลัมน์ที่มีค่าข้อมูล ในกรณีเหล่านี้ ต้องใช้ 1 ไบต์เพื่อจัดเก็บความยาวของคอลัมน์ (ศูนย์) ค่าว่างต่อท้ายในแถวไม่จำเป็นต้องมีพื้นที่เก็บข้อมูล เนื่องจากส่วนหัวของแถวใหม่จะส่งสัญญาณว่าคอลัมน์ที่เหลือในแถวก่อนหน้านั้นเป็นค่าว่าง ตัวอย่างเช่น หากสามคอลัมน์สุดท้ายของตารางเป็นค่าว่าง ก็จะไม่มีการจัดเก็บข้อมูลสำหรับคอลัมน์เหล่านี้

จากข้อมูลเหล่านี้ เราสร้างการใช้เหตุผล เราถือว่าฐานข้อมูลใช้การเข้ารหัส AL32UTF8 ในการเข้ารหัสนี้ ตัวอักษรรัสเซียจะมีขนาด 2 ไบต์

1) A และ X ค่าของฟิลด์ '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 และ Z. คล้ายกับกรณีก่อนหน้า ค่าในช่อง 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);

  • ประมาณสิบ
  • ประมาณร้อย
  • ประมาณหลายพัน
  • ประมาณหมื่น

ตอบตามเอกสารของ Oracle (อ้างอิงจาก 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

ตอบตามเอกสารของ Oracle (อ้างอิงจาก 11.2):

ขีดจำกัดฐานข้อมูลแบบลอจิคัล

ชิ้น
ประเภทของขีดจำกัด
มูลค่าจำกัด

ดัชนี
ขนาดรวมของคอลัมน์ที่จัดทำดัชนี
75% ของขนาดบล็อกฐานข้อมูลลบค่าใช้จ่ายบางส่วน

ดังนั้น ขนาดรวมของคอลัมน์ที่จัดทำดัชนีไม่ควรเกิน 6Kb จะเกิดอะไรขึ้นต่อไปขึ้นอยู่กับการเข้ารหัสพื้นฐานที่เลือก สำหรับการเข้ารหัส AL32UTF8 อักขระหนึ่งตัวสามารถใช้พื้นที่ได้สูงสุด 4 ไบต์ ดังนั้นในกรณีที่เลวร้ายที่สุด ประมาณ 6 อักขระจะพอดีกับขนาด 1500 กิโลไบต์ ดังนั้น Oracle จะไม่อนุญาตให้สร้างดัชนีที่ N = 400 (เมื่อความยาวของคีย์ตัวพิมพ์เล็กที่สุดคือ 1600 อักขระ * 4 ไบต์ + ความยาวแถว) ในขณะที่ ที่ N = 200 (หรือน้อยกว่า) การสร้างดัชนีจะทำงานได้โดยไม่มีปัญหา

ตัวดำเนินการ INSERT พร้อมคำใบ้ APPEND ได้รับการออกแบบมาเพื่อโหลดข้อมูลในโหมดตรง จะเกิดอะไรขึ้นหากนำไปใช้กับตารางที่ทริกเกอร์ค้าง?

  • ข้อมูลจะถูกโหลดในโหมดตรง ทริกเกอร์จะทำงานตามที่คาดไว้
  • ข้อมูลจะถูกโหลดในโหมดตรง แต่ทริกเกอร์จะไม่ถูกดำเนินการ
  • ข้อมูลจะถูกโหลดในโหมดปกติ ทริกเกอร์จะทำงานตามที่ควรจะเป็น
  • ข้อมูลจะถูกโหลดในโหมดปกติ แต่ทริกเกอร์จะไม่ถูกดำเนินการ
  • ข้อมูลจะไม่ถูกโหลด ข้อผิดพลาดจะถูกบันทึก

ตอบโดยพื้นฐานแล้ว นี่เป็นคำถามเกี่ยวกับตรรกะมากกว่า เพื่อหาคำตอบที่ถูกต้อง ฉันขอแนะนำแบบจำลองการใช้เหตุผลต่อไปนี้:

  1. การแทรกในโหมดไดเร็กต์จะดำเนินการโดยการสร้างบล็อกข้อมูลโดยตรง โดยข้ามเอ็นจิ้น SQL ซึ่งช่วยให้มั่นใจได้ถึงความเร็วสูง ดังนั้น การรับรองว่าการดำเนินการของทริกเกอร์นั้นยากมาก หากไม่ใช่เป็นไปไม่ได้ และไม่มีประเด็นใดในเรื่องนี้ เนื่องจากจะยังคงทำให้การแทรกช้าลงอย่างมาก
  2. ความล้มเหลวในการดำเนินการทริกเกอร์จะนำไปสู่ความจริงที่ว่าหากข้อมูลในตารางเหมือนกันสถานะของฐานข้อมูลโดยรวม (ตารางอื่น) จะขึ้นอยู่กับโหมดที่แทรกข้อมูลนี้ สิ่งนี้จะทำลายความสมบูรณ์ของข้อมูลอย่างเห็นได้ชัด และไม่สามารถนำไปใช้เป็นโซลูชันในการผลิตได้
  3. โดยทั่วไปการไม่สามารถดำเนินการตามที่ร้องขอจะถือเป็นข้อผิดพลาด แต่ที่นี่ เราควรจำไว้ว่า APPEND เป็นเพียงคำใบ้ และตรรกะทั่วไปของคำใบ้ก็คือ จะต้องนำมาพิจารณาหากเป็นไปได้ แต่หากไม่เป็นเช่นนั้น ตัวดำเนินการจะถูกดำเนินการโดยไม่คำนึงถึงคำใบ้นั้นด้วย

ดังนั้นคำตอบที่คาดหวังก็คือ ข้อมูลจะถูกโหลดในโหมดปกติ (SQL) ทริกเกอร์จะเริ่มทำงาน

ตามเอกสารของ Oracle (อ้างอิงจาก 8.04):

การละเมิดข้อจำกัดจะทำให้คำสั่งดำเนินการตามลำดับ โดยใช้เส้นทางการแทรกแบบทั่วไป โดยไม่มีคำเตือนหรือข้อความแสดงข้อผิดพลาด ข้อยกเว้นคือข้อจำกัดของคำสั่งที่เข้าถึงตารางเดียวกันมากกว่าหนึ่งครั้งในธุรกรรม ซึ่งอาจทำให้เกิดข้อความแสดงข้อผิดพลาดได้
ตัวอย่างเช่น หากมีทริกเกอร์หรือ Referential Integrity ปรากฏบนตาราง คำใบ้ APPEND จะถูกละเว้นเมื่อคุณพยายามใช้ Direct-load 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);

  • สำเร็จลุล่วงไปด้วยดี
  • ความล้มเหลวเนื่องจากข้อผิดพลาดทางไวยากรณ์
  • ข้อผิดพลาด: ธุรกรรมอัตโนมัติไม่ถูกต้อง
  • ข้อผิดพลาดที่เกี่ยวข้องกับการซ้อนการโทรเกินจำนวนสูงสุด
  • ข้อผิดพลาดการละเมิดคีย์ต่างประเทศ
  • ข้อผิดพลาดที่เกี่ยวข้องกับการล็อค

ตอบตารางและทริกเกอร์ถูกสร้างขึ้นค่อนข้างถูกต้อง และการดำเนินการนี้ไม่ควรทำให้เกิดปัญหา อนุญาตให้ทำธุรกรรมอัตโนมัติในทริกเกอร์ได้ มิฉะนั้นจะไม่สามารถบันทึกได้ เป็นต้น

หลังจากแทรกแถวแรกแล้ว การเรียกใช้ทริกเกอร์ที่ประสบความสำเร็จจะทำให้แถวที่สองถูกแทรก ส่งผลให้ทริกเกอร์เริ่มทำงานอีกครั้ง โดยแทรกแถวที่สาม และต่อไปเรื่อยๆ จนกว่าคำสั่งจะล้มเหลวเนื่องจากการเรียกใช้เกินจำนวนการซ้อนสูงสุด อย่างไรก็ตาม มีประเด็นที่ละเอียดอ่อนอีกประการหนึ่งเข้ามามีบทบาท ในขณะที่ทริกเกอร์ถูกดำเนินการ การคอมมิตยังไม่เสร็จสิ้นสำหรับเรคคอร์ดที่แทรกครั้งแรก ดังนั้น ทริกเกอร์ที่ทำงานในธุรกรรมอัตโนมัติจะพยายามแทรกแถวที่อ้างอิงคีย์ต่างประเทศไปยังเรกคอร์ดที่ยังไม่ได้คอมมิตลงในตาราง ซึ่งส่งผลให้เกิดการรอ (ธุรกรรมแบบอัตโนมัติจะรอให้ธุรกรรมหลักกระทำเพื่อดูว่าสามารถแทรกข้อมูลได้หรือไม่) และในขณะเดียวกันธุรกรรมหลักก็รอให้ธุรกรรมแบบอัตโนมัติทำงานต่อไปหลังจากการทริกเกอร์ การหยุดชะงักเกิดขึ้น และเป็นผลให้ธุรกรรมอัตโนมัติถูกยกเลิกเนื่องจากเหตุผลที่เกี่ยวข้องกับการล็อค.

เฉพาะผู้ใช้ที่ลงทะเบียนเท่านั้นที่สามารถเข้าร่วมในการสำรวจได้ เข้าสู่ระบบ, โปรด.

มันยากที่จะ?

  • เช่นเดียวกับสองนิ้ว ฉันตัดสินใจทุกอย่างถูกต้องทันที

  • ไม่จริง ฉันผิดสองสามคำถาม

  • ฉันแก้ไขได้ถูกต้องครึ่งหนึ่งแล้ว

  • ฉันเดาคำตอบสองครั้ง!

  • ฉันจะเขียนในความคิดเห็น

ผู้ใช้ 14 คนโหวต ผู้ใช้ 10 รายงดออกเสียง

ที่มา: will.com

เพิ่มความคิดเห็น