การปรับปรุงการอัพเดทพร้อมกันใน Postgres


9

ฉันใช้คำสั่ง Postgres พร้อมกันเช่นนี้:

UPDATE foo SET bar = bar + 1 WHERE baz = 1234

แบบสอบถามแต่ละรายการมีผลต่อจำนวน K แถวคงที่และฉันไม่สามารถหาวิธีบังคับใช้ลำดับที่แถวนั้นได้รับการอัปเดตได้ฉันจะสิ้นสุดด้วยการหยุดชะงัก ขณะนี้ฉันแก้ไขปัญหาด้วยการบังคับใช้คำสั่งซื้อด้วยตนเอง แต่นั่นหมายความว่าฉันต้องดำเนินการค้นหามากกว่าที่ฉันต้องการในขณะที่เพิ่มความซับซ้อนในการค้นหาจาก O (log N + K) เป็น O (K log N)

มีวิธีการปรับปรุงประสิทธิภาพโดยไม่สิ้นสุดความเสี่ยงต่อการหยุดชะงักหรือไม่? ฉันสงสัยว่าการแทนที่(baz)ดัชนีด้วย(baz, id)ดัชนีอาจทำงานได้หาก Postgres อัปเดตแถวในลำดับเดียวกันกับที่สแกนไปแล้วนี่เป็นวิธีการที่คุ้มค่าหรือไม่


ฉันแนะนำให้คุณเพิ่มCREATE TABLEรหัส
ypercubeᵀᴹ

คำตอบ:


15

ไม่มีORDER BYในSQL UPDATEคำสั่ง Postgres อัปเดตแถวตามลำดับโดยพลการ:

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

แนวทางปฏิบัติที่ดีที่สุดของคุณน่าจะล็อคอย่างชัดเจนด้วยSELECT ... ORDER BY ... FOR UPDATEในแบบสอบถามย่อยหรือแบบสแตนด์อโลนSELECTในการทำธุรกรรม - ในระดับเริ่มต้นแยก "read มุ่งมั่น" การอ้างอิง Tom Lane บน pgsql-general :

ควรเป็นเรื่องถูกต้อง --- การล็อก FOR UPDATE เป็นขั้นตอนสุดท้ายเสมอในขั้นตอนการเลือก

สิ่งนี้ควรทำงาน:

BEGIN;

SELECT 1
FROM   foo 
WHERE  baz = 1234
ORDER  BY bar
FOR    UPDATE;

UPDATE foo
SET    bar = bar + 1
WHERE  baz = 1234;

COMMIT;

ดัชนีหลายคอลัมน์ใน(baz, bar)อาจเหมาะสำหรับประสิทธิภาพ แต่เนื่องจากbarมีการปรับปรุงจำนวนมากอย่างชัดเจนดัชนีคอลัมน์เดี่ยว(baz)อาจจะดีกว่า ขึ้นอยู่กับปัจจัยสองประการ วิธีการหลายแถวต่อbaz? มีการปรับปรุง HOTได้โดยไม่ต้องดัชนีหลายคอลัมน์หรือไม่ ...

หาก bazมีการอัปเดตพร้อมกันก็ยังมีโอกาสที่มุมกรณีที่ไม่น่าเป็นไปได้สำหรับความขัดแย้ง(ตามเอกสารประกอบ) :

เป็นไปได้สำหรับSELECTคำสั่งที่รันที่READ COMMITTED ระดับการแยกธุรกรรมและการใช้ORDER BYและส่วนคำสั่งล็อกเพื่อส่งคืนแถวตามลำดับ ...

นอกจากนี้หากคุณควรมีข้อ จำกัด เฉพาะที่เกี่ยวข้องbarให้พิจารณาDEFERRABLEข้อ จำกัดเพื่อหลีกเลี่ยงการละเมิดที่ไม่ซ้ำกันภายในคำสั่งเดียวกัน คำตอบที่เกี่ยวข้อง:


1
หากฉันสั่งโดยidหรือคอลัมน์ที่ไม่ซ้ำอื่น ๆ แทนที่จะbarเป็นกรณีมุมหรือประสิทธิภาพการทำงานใช่มั้ย
Alexei Averchenko

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