ในการตอบคำถามนี้อย่างถูกต้องคุณต้องตัดสินใจก่อน: "ลบ" หมายความว่าอะไรในบริบทของระบบ / แอปพลิเคชันนี้
เพื่อที่จะตอบว่าคำถามที่คุณต้องตอบคำถามอื่น ๆ : ทำไมจะบันทึกถูกลบ?
มีสาเหตุหลายประการที่ทำให้ผู้ใช้อาจต้องลบข้อมูล ฉันมักจะพบว่ามีเหตุผลหนึ่งประการ (ต่อตาราง) ว่าทำไมการลบอาจจำเป็น ตัวอย่างบางส่วนคือ:
- ในการเรียกคืนพื้นที่ว่างในดิสก์
- การลบที่จำเป็นตามนโยบายการเก็บรักษา / ความเป็นส่วนตัว;
- ข้อมูลที่เสียหาย / ไม่ถูกต้องไร้ความสามารถง่ายต่อการลบและสร้างใหม่มากกว่าการซ่อมแซม
- ส่วนใหญ่ของแถวจะถูกลบออกเช่นตารางบันทึก จำกัด ระเบียน X / วัน
นอกจากนี้ยังมีสาเหตุที่น่าสงสารสำหรับการลบอย่างหนัก (เพิ่มเติมเกี่ยวกับเหตุผลเหล่านี้ในภายหลัง):
- เพื่อแก้ไขข้อผิดพลาดเล็กน้อย ซึ่งมักจะเน้นความเกียจคร้านของผู้พัฒนาและ UI ที่เป็นมิตร
- ในการ "โมฆะ" ธุรกรรม (เช่นใบแจ้งหนี้ที่ไม่ควรถูกเรียกเก็บเงิน)
- เพราะคุณสามารถ
ทำไมคุณถามว่ามันเป็นเรื่องใหญ่จริงเหรอ? เกิดอะไรขึ้นกับ ole ที่ดี ' DELETE
?
- ในระบบใดก็ตามที่เชื่อมโยงกับเงินจากระยะไกลการลบอย่างหนักละเมิดความคาดหวังทางบัญชีทุกประเภทแม้ว่าจะย้ายไปที่ตารางเก็บถาวร / หลุมฝังศพ วิธีที่ถูกต้องในการจัดการนี้เป็นเหตุการณ์ย้อนหลัง
- ตารางเก็บถาวรมีแนวโน้มที่จะแตกต่างจากสคีสด หากคุณลืมแม้แต่คอลัมน์ที่เพิ่งเพิ่มใหม่หรือเรียงซ้อนคุณจะสูญเสียข้อมูลนั้นไปอย่างถาวร
- การลบฮาร์ดสามารถเป็นงานราคาแพงมากโดยเฉพาะอย่างยิ่งกับน้ำตก ผู้คนจำนวนมากไม่รู้ว่าการเรียงซ้อนมากกว่าหนึ่งระดับ (หรือในบางกรณีการเรียงซ้อนใด ๆขึ้นอยู่กับ DBMS) จะส่งผลให้การดำเนินการระดับระเบียนแทนการดำเนินการที่กำหนดไว้
- การลบฮาร์ดบ่อย ๆ ซ้ำ ๆ จะช่วยเพิ่มความเร็วในกระบวนการแยกส่วนดัชนี
ดังนั้นการลบแบบอ่อนจะดีกว่าใช่ไหม ไม่ไม่:
- การติดตั้งพรูกลายเป็นเรื่องยากมาก คุณมักจะจบลงด้วยสิ่งที่ปรากฏให้กับลูกค้าเป็นแถวกำพร้า
- คุณจะได้ติดตามการลบเพียงครั้งเดียว จะทำอย่างไรถ้าแถวถูกลบและลบหลายครั้ง?
- ประสิทธิภาพการอ่านลดลงแม้ว่าสิ่งนี้สามารถบรรเทาได้บ้างด้วยการแบ่งพาร์ติชันมุมมองและ / หรือดัชนีที่กรอง
- ดังที่ได้กล่าวไว้ก่อนหน้านี้มันอาจผิดกฎหมายในบางสถานการณ์ / เขตอำนาจศาล
ความจริงก็คือแนวทางทั้งสองนี้ผิด การลบผิด หากคุณกำลังถามคำถามนี้จริง ๆ ก็หมายความว่าคุณกำลังจำลองสถานะปัจจุบันแทนธุรกรรม นี่คือการปฏิบัติที่ไม่ดีและไม่ดีในฐานข้อมูลที่ดิน
Udi Dahan เขียนเกี่ยวกับเรื่องนี้ในไม่ลบ - เพียงไม่ นอกจากนี้มักจะเรียงลำดับของงานที่ทำธุรกรรมกิจกรรมหรือ (คำแนะนำของฉัน) เหตุการณ์ที่จริงหมายถึง "ลบ" ไม่เป็นไรถ้าคุณต้องการลดความผิดปกติลงในตาราง "สถานะปัจจุบัน" สำหรับการทำงาน แต่ทำหลังจากที่คุณจับแบบจำลองทรานแซคชันลงก่อนไม่ใช่
ในกรณีนี้คุณมี "ผู้ใช้" ผู้ใช้เป็นลูกค้าหลัก ลูกค้ามีความสัมพันธ์ทางธุรกิจกับคุณ ความสัมพันธ์นั้นไม่ได้หายไปในอากาศเพียงเพราะพวกเขายกเลิกบัญชีของพวกเขา สิ่งที่เกิดขึ้นจริงคือ:
- ลูกค้าสร้างบัญชี
- ลูกค้ายกเลิกบัญชี
- ลูกค้าต่ออายุบัญชี
- ลูกค้ายกเลิกบัญชี
- ...
ในทุกกรณีมันเป็นลูกค้ารายเดียวกันและอาจเป็นบัญชีเดียวกัน (เช่นการต่ออายุแต่ละบัญชีเป็นข้อตกลงการบริการใหม่) เหตุใดคุณจึงลบแถว แบบจำลองนี้ง่ายมาก:
+-----------+ +-------------+ +-----------------+
| Account | --->* | Agreement | --->* | AgreementStatus |
+-----------+ +-------------+ +----------------+
| Id | | Id | | AgreementId |
| Name | | AccountId | | EffectiveDate |
| Email | | ... | | StatusCode |
+-----------+ +-------------+ +-----------------+
แค่นั้นแหละ. นั่นคือทั้งหมดที่มีให้มัน คุณไม่จำเป็นต้องลบอะไรเลย ด้านบนคือการออกแบบที่ค่อนข้างธรรมดาที่รองรับความยืดหยุ่นที่ดี แต่คุณสามารถทำให้มันง่ายขึ้นเล็กน้อย คุณอาจตัดสินใจว่าคุณไม่ต้องการระดับ "ข้อตกลง" และเพียงแค่มี "บัญชี" ไปที่ตาราง "AccountStatus"
หากความต้องการในแอปพลิเคชันของคุณบ่อยครั้งคือการรับรายการข้อตกลง / บัญชีที่ใช้งานอยู่มันเป็นคำถามที่ยุ่งยากเล็กน้อย
CREATE VIEW ActiveAgreements AS
SELECT agg.Id, agg.AccountId, acc.Name, acc.Email, s.EffectiveDate, ...
FROM AgreementStatus s
INNER JOIN Agreement agg
ON agg.Id = s.AgreementId
INNER JOIN Account acc
ON acc.Id = agg.AccountId
WHERE s.StatusCode = 'ACTIVE'
AND NOT EXISTS
(
SELECT 1
FROM AgreementStatus so
WHERE so.AgreementId = s.AgreementId
AND so.EffectiveDate > s.EffectiveDate
)
และคุณทำเสร็จแล้ว ตอนนี้คุณมีบางสิ่งที่มีประโยชน์ทั้งหมดของการลบแบบอ่อน แต่ไม่มีข้อเสีย:
- เร็กคอร์ดที่ถูกโยงถึงเป็นปัญหาที่ไม่มีปัญหาเนื่องจากเร็กคอร์ดทั้งหมดสามารถมองเห็นได้ตลอดเวลา คุณเพียงแค่เลือกจากมุมมองอื่นเมื่อจำเป็น
- "การลบ" มักจะเป็นการดำเนินการที่ถูกอย่างไม่น่าเชื่อเพียงแค่แทรกแถวหนึ่งเข้าไปในตารางเหตุการณ์
- ไม่เคยมีโอกาสของการสูญเสียประวัติศาสตร์ใด ๆ ใด ๆที่เคยไม่ว่าคุณไม่ดีกรูขึ้น
- คุณยังสามารถลบบัญชีได้ยากหากคุณต้องการ (เช่นเหตุผลด้านความเป็นส่วนตัว) และพอใจกับความรู้ที่ว่าการลบจะเกิดขึ้นอย่างหมดจดและไม่รบกวนส่วนอื่น ๆ ของแอพ / ฐานข้อมูล
ปัญหาเดียวที่จะแก้ไขคือปัญหาประสิทธิภาพการทำงาน ในหลายกรณีมันกลายเป็นเรื่องที่ไม่เป็นปัญหาเพราะมีการทำดัชนีคลัสเตอร์AgreementStatus (AgreementId, EffectiveDate)
- มี I / O น้อยมากที่กำลังค้นหาที่นั่น แต่ถ้าเป็นปัญหาก็มีวิธีแก้ไขโดยใช้ทริกเกอร์มุมมองที่จัดทำดัชนี / เป็นรูปเป็นร่างเหตุการณ์ระดับแอปพลิเคชัน ฯลฯ
ไม่ต้องกังวลเกี่ยวกับประสิทธิภาพเร็วเกินไป - สิ่งสำคัญคือการออกแบบที่ถูกต้องและ "ถูกต้อง" ในกรณีนี้หมายถึงการใช้ฐานข้อมูลในแบบที่ฐานข้อมูลมีไว้เพื่อใช้เป็นระบบธุรกรรม