ฐานข้อมูลอัปเดตดัชนีในธุรกรรม ณ จุดใด


11

ฉันพยายามที่จะเข้าใจลำดับของเหตุการณ์ในส่วนแทรกที่ทั้งดัชนีและธุรกรรมเกี่ยวข้องกัน

ตัวอย่างเช่นสถานะเอกสารของ Oracle:

หากคุณสร้าง [หรือมี] ดัชนีอย่างน้อยหนึ่งรายการก่อนที่จะโหลดข้อมูลฐานข้อมูลจะต้องอัปเดตทุกดัชนีเมื่อแทรกแต่ละแถว

แต่จะเกิดอะไรขึ้นถ้าฉันสร้างธุรกรรมแทรกห้าแถวจากนั้นส่งมอบ? มีการอัพเดตดัชนีสำหรับทุกส่วนแทรกหรือเพียงจุดที่กำหนดไว้หรือไม่

ลอจิกบอกฉันว่าพวกเขาจะได้รับการอัปเดต ณ จุดส่งมอบเท่านั้นเนื่องจากดัชนีที่อัพเดตไม่สามารถใช้งานได้จนกว่าจะมีการบันทึกข้อมูลเหล่านั้น แต่นั่นเป็นเรื่องจริงหรือ

ถ้าเป็นเช่นนั้นเมื่อฉันมีการแทรก 1m แถวเพื่อประสิทธิภาพที่ดีที่สุดฉันควรทำคอมมิชชันขนาดใหญ่ของแถวทั้งหมดและไม่ใช่ 10 ทรานแซคชันของระเบียน 100k แน่นอนฉันตระหนักว่าความเสี่ยงนี้ย้อนกลับมากขึ้นถ้าแถว 999,999 ล้มเหลว

ขอโทษถ้าคำศัพท์ของฉันออกมาเล็กน้อย ฉันไม่ได้เป็น DBA โดยการค้าขาย ฉันไม่ได้สนใจในฐานข้อมูลเฉพาะมากเท่าฐานข้อมูลโดยทั่วไปถึงแม้ว่า Oracle และ Postgres เป็นสิ่งที่ฉันใช้มากที่สุด ฉันค้นหาในหัวข้อนี้ แต่ไม่พบคำตอบที่ชัดเจนจริงๆ

คำตอบ:


8

ฉันทำงานกับ SQL Server และ Oracle อาจมีข้อยกเว้นบางอย่าง แต่สำหรับแพลตฟอร์มเหล่านั้นคำตอบทั่วไปคือข้อมูลและดัชนีจะได้รับการปรับปรุงในเวลาเดียวกัน

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

สำหรับวิธีหนึ่งในการคิดเกี่ยวกับมันให้พิจารณาที่โต๊ะที่มีคีย์หลัก ใน SQL Server และ Oracle สิ่งนี้ถูกนำไปใช้เป็นดัชนี เวลาส่วนใหญ่ที่เราต้องการให้มีข้อผิดพลาดทันทีหากมีการINSERTทำซึ่งจะเป็นการละเมิดคีย์หลัก เพื่อที่จะเกิดขึ้นดัชนีจะต้องปรับปรุงในเวลาเดียวกันกับข้อมูล โปรดทราบว่าแพลตฟอร์มอื่น ๆ เช่น Postgres อนุญาตข้อ จำกัด รอการตัดบัญชีซึ่งจะถูกตรวจสอบเฉพาะเมื่อมีการทำธุรกรรม

นี่คือตัวอย่างของ Oracle ฉบับย่อที่แสดงกรณีทั่วไป:

CREATE TABLE X_TABLE (PK INT NULL, PRIMARY KEY (PK));

INSERT INTO X_TABLE VALUES (1);
INSERT INTO X_TABLE VALUES (1); -- no commit

INSERTคำสั่งที่สองส่งข้อผิดพลาด:

ข้อผิดพลาด SQL: ORA-00001: ข้อ จำกัด ที่ไม่ซ้ำกัน (XXXXXX.SYS_C00384850) ละเมิด

00001. 00000 - "ละเมิดข้อ จำกัด ที่ไม่ซ้ำกัน (% s.% s) ที่ละเมิด"

* สาเหตุ: คำสั่ง UPDATE หรือ INSERT พยายามแทรกคีย์ที่ซ้ำกัน สำหรับ Trusted Oracle ที่กำหนดค่าในโหมด DBMS MAC คุณอาจเห็นข้อความนี้หากมีรายการที่ซ้ำกันอยู่ในระดับที่แตกต่างกัน

* การกระทำ: ลบข้อ จำกัด ที่ไม่ซ้ำกันหรือไม่ใส่รหัส

หากคุณต้องการดูการดำเนินการปรับปรุงดัชนีด้านล่างนี้เป็นการสาธิตอย่างง่ายใน SQL Server ขั้นแรกสร้างตารางสองคอลัมน์ที่มีหนึ่งล้านแถวและดัชนีแบบไม่รวมกลุ่มในVALคอลัมน์:

DROP TABLE IF EXISTS X_TABLE_IX;

CREATE TABLE X_TABLE_IX (
ID INT NOT NULL,
VAL VARCHAR(10) NOT NULL
PRIMARY KEY (ID)
);

CREATE INDEX X_INDEX ON X_TABLE_IX (VAL);

-- insert one million rows with N from 1 to 1000000
INSERT INTO X_TABLE_IX
SELECT N, N FROM dbo.Getnums(1000000);

แบบสอบถามต่อไปนี้สามารถใช้ดัชนี nonclustered เนื่องจากดัชนีเป็นดัชนีครอบคลุมสำหรับแบบสอบถามนั้น มันมีข้อมูลทั้งหมดที่จำเป็นในการดำเนินการ ตามที่คาดไว้ไม่มีการส่งคืน

SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';

แบบสอบถาม 1

ทีนี้มาเริ่มทรานแซคชันและอัพเดทVALแถวเกือบทั้งหมดในตาราง:

BEGIN TRANSACTION

UPDATE X_TABLE_IX
SET VAL = 'A'
WHERE ID <> 1;

นี่เป็นส่วนหนึ่งของแผนแบบสอบถามสำหรับสิ่งนั้น:

แบบสอบถาม 2

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

ด้วยการทำธุรกรรมยังไม่ได้รับการยอมรับมาทบทวนSELECTแบบสอบถามจากด้านบน

SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';

ป้อนคำอธิบายรูปภาพที่นี่

เครื่องมือเพิ่มประสิทธิภาพการสืบค้นยังคงสามารถใช้ดัชนีได้และในครั้งนี้คาดว่าจะมีการส่งคืนแถว 999999 การดำเนินการแบบสอบถามส่งคืนผลลัพธ์ที่คาดหวัง

นั่นเป็นตัวอย่างที่ง่าย แต่หวังว่ามันจะเคลียร์สิ่งต่าง ๆ ออกไปเล็กน้อย

นอกจากนี้ฉันทราบว่ามีบางกรณีที่อาจเป็นที่ถกเถียงกันอยู่ว่าดัชนีไม่ได้รับการอัพเดตทันที สิ่งนี้ทำเพื่อเหตุผลด้านประสิทธิภาพและผู้ใช้ไม่ควรเห็นข้อมูลที่ไม่สอดคล้องกัน ตัวอย่างเช่นการลบบางครั้งจะไม่ถูกนำไปใช้กับดัชนีใน SQL Server อย่างสมบูรณ์ กระบวนการพื้นหลังทำงานและล้างข้อมูลในที่สุด คุณสามารถอ่านเกี่ยวกับบันทึกผีหากคุณอยากรู้


นั่นเป็นคำตอบที่ยอดเยี่ยม - และยังตอบอีกสิ่งที่ฉันสงสัย: ไม่ว่าจะมีการละเมิดคีย์หลัก (หรือคล้ายกัน) ในส่วนแทรกหรือบนคอมมิท ขอบคุณสำหรับคำตอบที่สมบูรณ์
Mark Ireland

คำถามที่เกี่ยวข้อง (เกี่ยวกับเมื่อมีการละเมิดข้อ จำกัด เกิดขึ้น) เกี่ยวข้องกับว่าคุณใช้ธุรกรรมที่เลื่อนออกไปหรือไม่ ยกตัวอย่างเช่น SQL Server ยังไม่ได้ใช้งานการทำธุรกรรมรอการตัดบัญชีดังนั้นการละเมิดทั้งหมดที่เกิดขึ้นในตอนท้ายของงบ DBMS อื่นมี (Postgres เช่นแม้ว่าจะไม่ใช่ข้อ จำกัด ทุกประเภท) ดังนั้นเมื่อคุณมีข้อ จำกัด รอการตัดบัญชีการละเมิดจะถูกตรวจสอบที่ขั้นตอนการยอมรับของการทำธุรกรรม)
ypercubeᵀᴹ

Oracle ยังสนับสนุนข้อ จำกัด รอการตัดบัญชี
BobC

1

ประสบการณ์ของฉันคือการแทรกแถว 1,000,000 จริง ๆ แล้วต้องใช้ทรัพยากรเพิ่มเติมและใช้เวลานานกว่าให้เสร็จสมบูรณ์กว่าถ้าคุณใช้การแทรกชุดงาน ตัวอย่างนี้สามารถนำไปใช้กับตัวอย่าง 100 แทรก 10,000 แถว

สิ่งนี้จะช่วยลดโอเวอร์เฮดของแบตช์ที่ถูกแทรกและถ้าแบทช์ล้มเหลวมันจะเป็นการย้อนกลับที่เล็กกว่า

ในกรณีใด ๆ สำหรับ SQL Server จะมียูทิลิตีbcpหรือคำสั่งBULK INSERTซึ่งสามารถใช้ในการทำแบทช์แทรก

และแน่นอนคุณสามารถใช้รหัสของคุณเองสำหรับการจัดการแนวทางนี้


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