จัดโครงสร้างฐานข้อมูลของคุณ

ก่อนจะเริ่ม

ก่อนที่คุณจะสามารถใช้ เรียลไทม์ฐานข้อมูล คุณต้องไปที่:

  • ลงทะเบียนโครงการ Unity ของคุณและกำหนดค่าให้ใช้ Firebase

    • หากโปรเจ็กต์ Unity ของคุณใช้ Firebase อยู่แล้ว แสดงว่าได้ลงทะเบียนและกำหนดค่าสำหรับ Firebase แล้ว

    • หากคุณไม่ได้มีโครงการเอกภาพคุณสามารถดาวน์โหลด แอปพลิเคตัวอย่าง

  • เพิ่ม Firebase สามัคคี SDK (เฉพาะ FirebaseDatabase.unitypackage ) ให้กับโครงการความสามัคคีของคุณ

หมายเหตุว่าการเพิ่ม Firebase กับโครงการความสามัคคีของคุณเกี่ยวข้องกับงานทั้งใน Firebase คอนโซล และในโครงการความสามัคคีของคุณเปิด (ตัวอย่างเช่นคุณดาวน์โหลดไฟล์การกำหนดค่า Firebase จากคอนโซลแล้วย้ายไปลงในโครงการความสามัคคีของคุณ)

ข้อมูลโครงสร้าง

คู่มือนี้ครอบคลุมแนวคิดหลักบางประการในสถาปัตยกรรมข้อมูลและแนวทางปฏิบัติที่ดีที่สุดสำหรับการจัดโครงสร้างข้อมูล JSON ในฐานข้อมูลเรียลไทม์ของ Firebase

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

โครงสร้างข้อมูลเป็นอย่างไร: เป็นต้นไม้ JSON

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

ถ้าคุณสร้างคีย์ของคุณเองพวกเขาจะต้องเข้ารหัส UTF-8 สามารถสูงสุด 768 . , $ , # , [ , ] , / หรือการควบคุมตัวอักษร ASCII 0-31 หรือ 127 คุณไม่สามารถใช้การควบคุมตัวอักษร ASCII ในค่าของตัวเองอย่างใดอย่างหนึ่ง

ตัวอย่างเช่น พิจารณาแอปพลิเคชันแชทที่อนุญาตให้ผู้ใช้จัดเก็บโปรไฟล์พื้นฐานและรายชื่อผู้ติดต่อ รายละเอียดผู้ใช้ทั่วไปจะอยู่ที่เส้นทางเช่น /users/$uid ผู้ใช้ alovelace อาจมีรายการฐานข้อมูลที่มีลักษณะบางอย่างเช่นนี้

{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      "contacts": { "ghopper": true },
    },
    "ghopper": { ... },
    "eclarke": { ... }
  }
}

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

แนวปฏิบัติที่ดีที่สุดสำหรับโครงสร้างข้อมูล

หลีกเลี่ยงการซ้อนข้อมูล

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

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

{
  // This is a poorly nested data architecture, because iterating the children
  // of the "chats" node to get a list of conversation titles requires
  // potentially downloading hundreds of megabytes of messages
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "messages": {
        "m1": { "sender": "ghopper", "message": "Relay malfunction found. Cause: moth." },
        "m2": { ... },
        // a very long list of messages
      }
    },
    "two": { ... }
  }
}

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

ปรับโครงสร้างข้อมูลให้เรียบ

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

{
  // Chats contains only meta info about each conversation
  // stored under the chats's unique ID
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
      "timestamp": 1459361875666
    },
    "two": { ... },
    "three": { ... }
  },

  // Conversation members are easily accessible
  // and stored by chat conversation ID
  "members": {
    // we'll talk about indices like this below
    "one": {
      "ghopper": true,
      "alovelace": true,
      "eclarke": true
    },
    "two": { ... },
    "three": { ... }
  },

  // Messages are separate from data we may want to iterate quickly
  // but still easily paginated and queried, and organized by chat
  // conversation ID
  "messages": {
    "one": {
      "m1": {
        "name": "eclarke",
        "message": "The relay seems to be malfunctioning.",
        "timestamp": 1459361875337
      },
      "m2": { ... },
      "m3": { ... }
    },
    "two": { ... },
    "three": { ... }
  }
}

ตอนนี้สามารถทำซ้ำผ่านรายการห้องโดยการดาวน์โหลดเพียงไม่กี่ไบต์ต่อการสนทนา ดึงข้อมูลเมตาอย่างรวดเร็วสำหรับรายการหรือแสดงห้องใน UI สามารถดึงข้อความแยกกันและแสดงเมื่อมาถึง ทำให้ UI ตอบสนองและรวดเร็ว

สร้างข้อมูลที่ปรับขนาด

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

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

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

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

// An index to track Ada's memberships
{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      // Index Ada's groups in her profile
      "groups": {
         // the value here doesn't matter, just that the key exists
         "techpioneers": true,
         "womentechmakers": true
      }
    },
    ...
  },
  "groups": {
    "techpioneers": {
      "name": "Historical Tech Pioneers",
      "members": {
        "alovelace": true,
        "ghopper": true,
        "eclarke": true
      }
    },
    ...
  }
}

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

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

วิธีการนี้ inverting ข้อมูลโดยรายชื่อรหัสเป็นคีย์และการตั้งค่าเป็นจริงทำให้การตรวจสอบที่สำคัญเป็นง่ายๆเป็นอ่าน /users/$uid/groups/$group_id และการตรวจสอบถ้ามันเป็น null ดัชนีนั้นเร็วกว่าและมีประสิทธิภาพมากกว่าการสืบค้นหรือสแกนข้อมูล

ขั้นตอนถัดไป