การ Denormalize

บทแทรก 10.5

แปลไปแล้ว

ในบทนี้ คุณจะได้

  • เข้าใจว่าการ denormalize คืออะไร
  • เปรียบเทียบ Mongo กับฐานข้อมูลทั่วไป
  • รู้ว่าเมื่อไรถึงไม่ควร denormalize
  • การทำ Denormalize กับข้อมูลคือ การไม่เก็บข้อมูลนั้นในรูปแบบ “ปกติ” โดย denormalize ยังหมายถึงการที่มีข้อมูลเดียวกันหลายๆชุดไว้เอาเรียกใช้งาน

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

    การ Denormalize บ่อยๆ หมายถึงงานที่เพิ่มขึ้นของนักพัฒนา ในตัวอย่างของเรานั้น ทุกครั้งที่เราเพิ่มหรือลบข้อคิดเห็น เราก็จำเป็นต้องอัพเดทข้อมูลข่าวที่เกี่ยวข้องเพื่อให้มั่นใจว่าฟิลด์ commentsCount ยังคงมีค่าที่ถูกต้อง และนี่ก็เป็นสาเหตุโดยตรงที่ฐานข้อมูลแบบ relational เช่น MySQL ไม่ค่อยถูกโฉลกกับแนวทางนี้

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

    การเผยแพร่แบบพิเศษ

    มัน เป็น ไปได้ที่จะสร้างการเผยแพร่แบบพิเศษที่ส่งแค่จำนวนข้อคิดเห็นที่เราสนใจมาให้ (เช่น นับจำนวนข้อคิดเห็นของข่าวทั้งหมดที่เรากำลังดูอยู่ ด้วยการรันการสืบค้นที่เซิร์ฟเวอร์)

    แต่ก็ควรต้องพิจารณาด้วยว่า ความซับซ้อนของโค้ดการเผยแพร่แบบนั้น ก็ไม่ควรจะมากไปกว่าความยากที่เกิดจากการ denormalize

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

    การฝังเอกสารลงไป หรือ การใช้หลายคอลเลกชั่น

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

    เห็นได้ชัดว่า เครื่องมือหลายๆตัวของ Meteor ช่วยให้เราทำงานได้ดีขึ้นเมื่อทำงานที่ระดับของคอลเลกชั่น อย่างเช่น

    1. ตัวช่วย {{#each}} ทำงานได้อย่างมีประสิทธิภาพมาก เมื่อทำงานซ้ำกับเคอร์เซอร์ (ผลลัพธ์ของคำสั่ง collection.find()) แต่จะไม่ได้ผลเหมือนเดิม ถ้าให้ทำซ้ำกับอาร์เรย์ของอ็อบเจกต์ภายในเอกสารที่ใหญ่ขึ้น
    2. allow และ deny ทำงานที่ระดับเอกสาร และนั่นทำให้เป็นการง่ายที่จะทำให้แน่ใจว่า การเปลี่ยนแปลงใดๆกับข้อคิดเห็นแต่ละข้อเป็นเรื่องถูกต้อง ในมุมมองที่ว่ามันจะซับซ้อนมากขึ้นเมื่อเราทำงานที่ระดับของข่าว
    3. DDP ทำงานที่ระดับของแอททริบิวต์ในระดับบนของเอกสาร ซึ่งอาจมีความหมายว่า ถ้า comments เป็นคุณสมบัติหนึ่งของ post ทุกครั้งที่ข้อคิดเห็นถูกสร้างขึ้นในหน้าข่าว เซิร์ฟเวอร์ก็จะส่งข้อคิดเห็นทั้งหมดของข่าวที่อัพเดทแล้วกลับไปที่ไคลเอนต์แต่ละตัวที่เชื่อมต่ออยู่
    4. การเผยแพร่และบอกรับข้อมูล เป็นงานที่ง่ายกว่ามาก ถ้าทำงานในระดับของเอกสาร ตัวอย่างเช่น ถ้าเราต้องการแบ่งหน้าข้อคิดเห็นในหน้าข่าว เราอาจพบว่ามันยากที่จะทำ ยกเว้นถ้าข้อคิดเห็นอยู่ในคอลเลกชั่นของมันเอง

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

    ข้อเสียของการ Denormalize

    มีข้อโต้แย้งที่ดีว่า คุณ ไม่ควร denormalize ข้อมูลของคุณ เพื่อให้คุณเข้าใจเรื่องที่แย้งกับการ denormalize เราแนะนำให้คุณอ่าน Why You Should Never Use MongoDB เขียนโดย Sarah Mei