OracleBulkCopy ทำอะไรเป็นพิเศษโดยเฉพาะและฉันจะเพิ่มประสิทธิภาพได้อย่างไร


14

ในการสรุปข้อมูลเฉพาะ: เราจำเป็นต้องทำขั้นตอนประมาณ 5 ล้านแถวในฐานข้อมูลผู้จำหน่าย (Oracle) ทุกอย่างทำงานได้อย่างยอดเยี่ยมสำหรับแถวที่มีขนาด 500k โดยใช้OracleBulkCopy(ODP.NET) แต่เมื่อเราพยายามที่จะขยายขนาดสูงสุด 5M ประสิทธิภาพการทำงานจะเริ่มช้าลงเมื่อทำการรวบรวมข้อมูลเมื่อมันมาถึงเครื่องหมาย 1M จะช้าลงเรื่อย ๆ เมื่อโหลดแถวมากขึ้น หมดเวลาหลังจาก 3 ชั่วโมงหรือมากกว่านั้น

ฉันสงสัยว่ามันเกี่ยวข้องกับคีย์หลักบนโต๊ะ แต่ฉันได้สืบค้นฟอรัม Oracle และ Stack Overflow เพื่อดูข้อมูลและสิ่งที่ฉันอ่านขัดแย้งมาก (เช่นกันโพสต์จำนวนมากดูเหมือนจะขัดแย้งกัน ) . ฉันหวังว่าใครบางคนสามารถตั้งค่าการบันทึกตรงคำถามที่เกี่ยวข้องอย่างใกล้ชิดเกี่ยวกับกระบวนการ:

  1. ที่ไม่OracleBulkCopyระดับธรรมดาหรือใช้โดยตรงเส้นทางโหลด? มีวิธีที่ฉันสามารถยืนยันสิ่งนี้ไม่ทางใดก็ทางหนึ่งได้หรือไม่?

  2. สมมติว่ามันไม่ใช้โดยตรงเส้นทางโหลด: มันเป็นความจริงว่า Oracle จะตั้งค่าดัชนีทั้งหมดจะใช้ไม่ได้ในระหว่างการโหลดและทำให้พวกเขากลับมาออนไลน์หลังจากนั้น? ฉันได้อ่านแถลงการณ์หลายฉบับเกี่ยวกับเอฟเฟกต์นี้ แต่ไม่สามารถยืนยันได้อีก

  3. ถ้า # 2 เป็นจริงแล้วมันควรสร้างความแตกต่างใด ๆ ที่ดัชนีอยู่บนตารางก่อนที่ฉันจะเริ่มต้นการดำเนินการคัดลอกจำนวนมาก? ถ้าเป็นเช่นนั้นทำไม

  4. เกี่ยวข้องกับ # 3 มีความแตกต่างในทางปฏิบัติโดยทั่วไประหว่างการโหลดจำนวนมากกับดัชนีที่ใช้ไม่ได้กับการลดลงดัชนีจริงก่อนที่จะโหลดและสร้างใหม่ในภายหลังหรือไม่

  5. หาก # 2 คือไม่ถูกต้องหรือหากมีบางประการที่ฉันไม่เข้าใจแล้วมันจะสร้างความแตกต่างใด ๆอย่างชัดเจนทำให้ดัชนีไม่สามารถใช้งานก่อนที่จะโหลดทั้งกลุ่มแล้ว อย่างชัดเจนสร้างมันหลังจากนั้น?

  6. มีสิ่งอื่นใดนอกเหนือจากการสร้างดัชนีซึ่งอาจทำให้การดำเนินการคัดลอกจำนวนมากเติบโตช้าลงอย่างต่อเนื่องเมื่อมีการเพิ่มบันทึกมากขึ้นหรือไม่ (อาจเกี่ยวข้องกับการบันทึกแม้ว่าฉันจะคาดหวังว่าการดำเนินการจำนวนมากจะไม่ถูกบันทึกไว้)

  7. หากไม่มีวิธีอื่นที่จะทำให้ประสิทธิภาพการทำงานลดลงจากการลดระดับ PK / ดัชนีก่อนสิ่งที่ฉันสามารถทำได้เพื่อให้แน่ใจว่าดัชนีจะไม่หายไปอย่างสมบูรณ์เช่นถ้าการเชื่อมต่อกับฐานข้อมูลหายไป กลางกระบวนการ


หมายเหตุด้านข้าง: ข้อมูลที่ถูกคัดลอกนั้นมีการเรียงลำดับแล้วตาม PK ซึ่งเป็นดัชนีเดียวในตาราง
Aaronaught

คุณใช้ DataReader เพื่ออ่านข้อมูลจากแหล่งที่มาหรือไม่
bernd_k

@bernd_k: ไม่โหลดจากหน่วยความจำทั้งหมด แน่นอนว่าไม่ใช่แหล่งที่มาของปัญหา
Aaronaught

คำตอบ:


13

อีกไม่กี่วันของการอ่านและการทดลองและฉันก็สามารถที่จะตอบคำถามเหล่านี้ (ส่วนใหญ่):

  1. ฉันพบสิ่งนี้ฝังอยู่ในเอกสาร ODP.NET (แดกดันไม่อยู่ในOracleBulkCopyเอกสาร):

    คุณลักษณะการคัดลอกจำนวนมาก ODP.NET ใช้วิธีโหลดเส้นทางโดยตรงซึ่งคล้ายกับ แต่ไม่เหมือนกับ Oracle SQL * Loader การใช้โหลดพา ธ โดยตรงนั้นเร็วกว่าการโหลดแบบเดิม (โดยใช้INSERTคำสั่งSQL ทั่วไป)

    จึงปรากฏว่ามันไม่ใช้เส้นทางตรง

  2. สิ่งนี้ฉันสามารถตรวจสอบได้ด้วยการดำเนินการคัดลอกจำนวนมากและรับคุณสมบัติดัชนีจาก SQL Developer ดัชนีไม่ปรากฏเป็นUNUSABLEในขณะที่คัดลอกขนาดใหญ่อยู่ในความคืบหน้า อย่างไรก็ตามฉันยังค้นพบว่าOracleBulkCopy.WriteToServerจะปฏิเสธที่จะเรียกใช้ถ้าดัชนีเริ่มต้นในUNUSABLEสถานะดังนั้นชัดเจนว่ามีมากขึ้นที่นี่เพราะถ้ามันง่ายเหมือนการปิดการใช้งานและการสร้างดัชนีใหม่แล้วมันไม่ควรสนใจเกี่ยวกับสถานะเริ่มต้น

  3. มันสร้างความแตกต่างโดยเฉพาะถ้าดัชนีเป็นข้อ จำกัดเช่นกัน พบอัญมณีเล็ก ๆ นี้ในเอกสารที่ลิงก์ด้านบน:

    Enabled Constraints
    ในระหว่างการคัดลอกข้อมูลจำนวนมากของ Oracle ข้อ จำกัด ต่อไปนี้จะถูกเปิดใช้งานโดยอัตโนมัติ

    • NOT NULL
    • UNIQUE
    • PRIMARY KEY (ข้อ จำกัด เฉพาะในคอลัมน์ที่ไม่เป็นโมฆะ)

    NOT NULLมีการตรวจสอบข้อ จำกัด ณ เวลาสร้างอาร์เรย์คอลัมน์ แถวที่ละเมิดNOT NULLข้อ จำกัด จะถูกปฏิเสธ

    UNIQUEข้อ จำกัด จะถูกตรวจสอบเมื่อดัชนีถูกสร้างใหม่ในตอนท้ายของการโหลด ดัชนีจะถูกปล่อยให้อยู่ในสถานะไม่สามารถใช้ดัชนีได้หากฝ่าฝืนUNIQUEข้อ จำกัด

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

  4. OracleBulkCopyฉันไม่แน่ใจว่าความแตกต่างที่สังเกตอยู่ภายในออราเคิลเองหรือเพียงแค่การเล่นโวหารของที่ คณะลูกขุนยังคงออกในนี้

  5. OracleBulkCopyจะโยนข้อยกเว้นหากดัชนีอยู่ในUNUSABLEสถานะเริ่มต้นดังนั้นจึงเป็นจุดที่สงสัยจริงๆ

  6. หากมีจะมีปัจจัยอื่น ๆ ดัชนี (และดัชนี PK โดยเฉพาะ) ยังคงเป็นสิ่งที่สำคัญที่สุดที่ผมพบโดย:

  7. การสร้างตารางชั่วคราวทั่วโลกด้วยสคีมาเดียวกัน (โดยใช้CREATE AS) จากนั้นคัดลอกจำนวนมากลงในตารางชั่วคราวและในที่สุดก็ทำแบบเก่าธรรมดาINSERTจากตารางชั่วคราวลงในตารางจริง เนื่องจากตาราง temp ไม่มีดัชนีสำเนาจำนวนมากจึงเกิดขึ้นอย่างรวดเร็วและสุดท้ายINSERTก็รวดเร็วเนื่องจากข้อมูลอยู่ในตารางอยู่แล้ว (ฉันยังไม่ได้ลองใส่คำใบ้ต่อท้ายเนื่องจากคัดลอกตารางต่อตารางแถว 5M ใช้เวลาน้อยกว่า 1 นาที)

    ฉันยังไม่แน่ใจว่าจะมี ramifications ของ (ab) โดยใช้พื้นที่ตารางชั่วคราวด้วยวิธีนี้ แต่จนถึงขณะนี้มันก็ไม่ได้ทำให้ฉันมีปัญหาใด ๆ และมันปลอดภัยกว่าทางเลือกอื่น ๆ ในการป้องกันการทุจริตของแถวทั้งสองหรือดัชนี

    ความสำเร็จของสิ่งนี้ค่อนข้างชัดเจนแสดงให้เห็นว่าดัชนี PK เป็นปัญหาเนื่องจากเป็นความแตกต่างในทางปฏิบัติเพียงอย่างเดียวระหว่างตารางชั่วคราวและตารางถาวร - ทั้งคู่เริ่มต้นด้วยศูนย์แถวในระหว่างการทดสอบประสิทธิภาพ

สรุป:อย่ากังวลที่จะพยายามคัดลอกแถวมากกว่า 100,000 แถวลงในตาราง Oracle ที่จัดทำดัชนีโดยใช้ ODP.NET วางดัชนี (หากคุณไม่ต้องการใช้จริง) หรือ "โหลดล่วงหน้า" ข้อมูลลงในตารางอื่น (ไม่ได้จัดทำดัชนี)


ฉันไม่แน่ใจเกี่ยวกับการตรวจสอบข้อ จำกัด ของคีย์หลัก ฉันยินดีที่จะแทรกข้อมูลเดียวกันจำนวนมากลงในตาราง Oracle 2 ครั้งและเลือก * แสดง 2 แถวที่ซ้ำกัน ในสถานะนั้นจะไม่สามารถลบได้ แต่ตารางการตัดจะช่วยให้กลับไปอยู่ในสถานะที่สะอาด
bernd_k

@bernd_k: เป็นไปไม่ได้เพราะดัชนีDelete UNUSABLEนั่นคือผลลัพธ์ของการตรวจสอบข้อ จำกัด ที่เกิดขึ้นในตอนท้ายของการคัดลอกจำนวนมาก
Aaronaught

ฉันมี PowerShell skript กำลังเรียกใช้การดึงข้อมูลจำนวนมากลงในฐานข้อมูล Oracle จากตัวอ่านข้อมูล SQL Server ทุกตารางเป้าหมายที่มีคีย์หลักและฉันไม่มีปัญหากับตารางที่มีแถวสูงถึง 205278 แต่ฉันระมัดระวังที่จะเต็มตารางหลักก่อนที่จะกรอกตารางรายละเอียด ฉันไม่ได้ลบดัชนีอื่น ๆ บนตารางและฉันไม่มีปัญหาเมื่อตารางว่างเปล่าในตอนแรก
bernd_k

@bernd_k: ใช่ฉันไม่ได้มีปัญหามากเกินไปในเล่มนั้น (ดูย่อหน้าสุดท้ายของฉัน) เมื่อคุณเข้าถึงคนนับล้านว่ามันแย่มาก นอกจากนี้อาจมีความแตกต่างถ้าคุณล้างตารางในบางครั้งหลังจากที่คัดลอกจำนวนมากแต่ละชุด (อันนี้ไม่ถูกทำให้ว่างเปล่ามันจะถูกผนวกเข้ากับและคุณรู้ว่าดัชนีจะช้าลงอย่างไรเมื่อพวกมันใหญ่ขึ้น)
Aaronaught

อาจช่วยได้เมื่อคุณทำalter session set skip_unusable_indexes = true;
Wernfried Domscheit

1

นี่คือบทความจาก Oracle ซึ่งจะอธิบายเมื่อมันจะมีประโยชน์ในการใช้งานการแทรกจำนวนมากหรือไม่ นอกจากนี้ยังมีข้อมูลเชิงลึกเกี่ยวกับสิ่งที่เกิดขึ้นในระดับฐานข้อมูล

http://docs.oracle.com/cd/B28359_01/server.111/b28319/ldr_modes.htm


3
ลิงค์มีแนวโน้มที่จะเน่า; คุณอาจต้องการรวมข้อมูลที่เกี่ยวข้องจากลิงค์ในคำตอบของคุณ
mustaccio
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.