ประสิทธิภาพของทริกเกอร์ vs ขั้นตอนการจัดเก็บใน MySQL


11

โพสต์ที่นี่ใน DBA.StackExchange ( อะไรคือแนวทางปฏิบัติที่ดีที่สุดสำหรับทริกเกอร์เพื่อรักษาหมายเลขการแก้ไขเรคคอร์ด? ) ทำให้เกิดคำถามที่น่าสนใจ (อย่างน้อยก็น่าสนใจสำหรับฉัน) เกี่ยวกับประสิทธิภาพใน MySQL

บริบทคือเราต้องการแทรกระเบียนในตารางสำหรับแต่ละแถวที่มีการปรับปรุง ก่อนที่จะอัปเดตแถวเราต้องการเก็บค่าก่อนหน้าจากนั้นเพิ่มหนึ่งในคอลัมน์ (คอลัมน์ "รุ่น")

หากเราทำสิ่งนี้ภายในทริกเกอร์มันจะทำงานได้ดี สำหรับ MySQL ทริกเกอร์เป็นแบบทีละแถวดังนั้นมันจึงเป็นทางออกที่ง่าย เลือกข้อมูลในตารางปัจจุบันแทรกลงในตารางการบันทึกและอัปเดตคอลัมน์ "version" ในข้อมูลใหม่

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

ดังนั้นเมื่อมันมาถึงการแทรกนี้นี้จะมีประสิทธิภาพมากกว่าที่จะใช้วิธีการจัดเก็บตามชุดหรือวิธีการตามทริกเกอร์?

คำถามนี้มีไว้สำหรับ MySQL (เนื่องจากมีทริกเกอร์แบบทีละแถว) แม้ว่าจะสามารถนำไปใช้กับ DBMS ทริกเกอร์แบบแถวต่อแถวอื่น ๆ ได้


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

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

คำตอบ:


7

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

ตามที่MySQL Stored Procedure Programming , หน้า 256 ใต้หัว "Trigger Overhead" กล่าวว่า:

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

คำอธิบายเพิ่มเติมของค่าใช้จ่ายทริกเกอร์จะได้รับในหน้า 529-531 จุดสรุปจากส่วนนั้นระบุสิ่งต่อไปนี้:

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

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

เมื่อใช้ทริกเกอร์ในตาราง InnoDB และการเปลี่ยนแปลงการบันทึก

  • ตารางที่คุณเข้าสู่ระบบคือ InnoDB
  • คุณปิดการเติมข้อความอัตโนมัติ
  • คุณตั้งค่าเริ่มต้นการทำธุรกรรม ... คอมมิชชัน / ย้อนกลับบล็อกอย่างทั่วถึง

ด้วยวิธีนี้บันทึกการตรวจสอบจะได้ประโยชน์จาก COMMIT / ROLLBACK เช่นเดียวกับตารางหลัก

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

ข้อแม้

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

ใช้ฮาร์ดแวร์สินค้าโภคภัณฑ์สร้างเซิร์ฟเวอร์ DB อีกสองรายการ

เซิร์ฟเวอร์นี้จะลดการเขียน I / O บนฐานข้อมูลหลัก (MD) เนื่องจากการบันทึกการตรวจสอบ นี่คือวิธีที่คุณสามารถทำได้:

ขั้นตอนที่ 01) เปิดการบันทึกแบบไบนารีในฐานข้อมูลหลัก

ขั้นตอนที่ 02) ใช้เซิร์ฟเวอร์ราคาไม่แพงตั้งค่า MySQL (รุ่นเดียวกันกับ MD) โดยเปิดใช้งานการบันทึกแบบไบนารี นี่จะเป็น DM ตั้งค่าการจำลองแบบจาก MD เป็น DM

ขั้นตอนที่ 03) ใช้เซิร์ฟเวอร์ราคาถูกตัวที่สองตั้งค่า MySQL (รุ่นเดียวกันกับ MD) โดยปิดใช้งานการบันทึกแบบไบนารี การตั้งค่าแต่ละตารางการตรวจสอบการใช้--replicate ทำตาราง นี่จะเป็น AU ตั้งค่าการจำลองแบบจาก DM เป็น AU

ขั้นตอนที่ 04) mysqldump โครงสร้างตารางจาก MD และโหลดลงใน DM และ AU

ขั้นตอนที่ 05) แปลงตารางการตรวจสอบทั้งหมดใน MD เพื่อใช้เครื่องมือเก็บข้อมูล BLACKHOLE

ขั้นตอนที่ 06) แปลงตารางทั้งหมดใน DM และ AU เพื่อใช้เครื่องมือเก็บข้อมูล BLACKHOLE

ขั้นตอนที่ 07) แปลงตารางการตรวจสอบทั้งหมดใน AU เพื่อใช้เครื่องมือจัดเก็บ MyISAM

เมื่อทำเสร็จแล้ว

  • DM จะทำซ้ำจาก MD และบันทึกข้อมูลในบันทึกไบนารีเท่านั้น
  • ด้วย--replicate-do-table filter บนตารางการตรวจสอบทั้งหมด AU จะทำซ้ำจาก DM

สิ่งนี้จะเก็บข้อมูลการตรวจสอบในเซิร์ฟเวอร์ฐานข้อมูลแยกต่างหากและยังลดการย่อยสลายการเขียน I / O ใด ๆ ที่ MD จะมีตามปกติ


คำตอบอันยิ่งใหญ่ +++ 1
b_dubb

1

นี่คือวิธีการดำเนินการอัปเดตนี้เป็นกลุ่ม

สำหรับตัวอย่างนี้

  • table_A มีรหัสคีย์หลัก
  • คุณสร้างตารางชื่อ table_A_Keys2Update โดยใช้ id เป็นคีย์หลัก
  • คุณเติม table_A_Keys2 อัปเดตด้วยรหัสจาก table_A ที่คุณรู้ว่าต้องอัปเดต

หากต้องการสร้าง table_A_Keys2Update ให้ทำดังนี้:

CREATE TABLE table_A_Keys2Update SELECT id FROM table_A;
ALTER TABLE table_A_Keys2Update ADD PRIMARY KEY (id);

หลังจากที่คุณเติม table_A_Keys2Update ด้วยรหัสที่ต้องมีการแก้ไขเพิ่มเติมให้ดำเนินการ UPDATE JOIN ต่อไปนี้เพื่อเพิ่มจำนวนการแก้ไขของแถวทั้งหมดที่มี id อยู่ทั้ง table_A และ table_A_Keys2Update:

UPDATE table_A A INNER JOIN table_A_Keys2Update B USING (id)
SET A.revision = A.revision + 1;

เคียวรีหนึ่งบรรทัดนี้สามารถแทนที่ทริกเกอร์และโพรซีเดอร์ที่เก็บไว้

หรือคุณสามารถวางแบบสอบถามนี้หนึ่งในขั้นตอนการจัดเก็บและเรียกว่าถ้าคุณต้องการ


มันเป็นส่วนแทรกที่ฉันอยากรู้ หากคุณใส่เข้าไปในการตรวจสอบเลือก <สิ่งใด> จาก <primary_table> WHERE <พารามิเตอร์จากกระบวนงานที่เก็บไว้>คุณสามารถแทรกจำนวนมากได้ ในการเรียกคุณจะเพียงแค่ค่าตรวจสอบ INSERT INTO <ข้อมูลจากแถวที่อัปเดต> ดังนั้นการแทรกแบบบรรทัดทีละบรรทัดจะเร็วกว่าการแทรกแบบกลุ่มหรือไม่
ริชาร์ด

เพื่อความเรียบง่ายทริกเกอร์จะดีกว่ามาก 1) หาก primary_table ไม่เคยพบเม็ด bulks ในช่วงเวลาสูงสุด 2) ข้อมูลการตรวจสอบจะต้องอ่านตามความต้องการ ณ เวลาใดก็ได้และ 3) เว็บไซต์ของคุณ เป็นผู้ดูแลการแสดงโฆษณาต่ำ
RolandoMySQLDBA
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.