Database messenger (bagian 1): kami merancang bingkai dasar

Bagaimana persyaratan bisnis dapat diterjemahkan ke dalam struktur data tertentu menggunakan contoh mendesain basis "dari awal" untuk messenger?



Basis data kami tidak akan sebesar dan terdistribusi seperti VKontakte atau Badoo , tetapi "menjadi", tetapi bagus - fungsional, cepat dan cocok untuk satu server PostgreSQL - sehingga Anda dapat menggunakan turunan terpisah dari layanan di suatu tempat di sisi, misalnya.

Oleh karena itu, kami tidak akan menyentuh masalah sharding, replikasi, dan sistem yang didistribusikan secara geografis, tetapi lebih fokus pada solusi rangkaian di dalam database.

Langkah 1: Sedikit kekhususan bisnis


Kami tidak akan mendesain perpesanan kami secara abstrak, tetapi menanamkannya di lingkungan jaringan sosial perusahaan . Artinya, orang-orang di tempat kami tidak "hanya berkirim pesan", tetapi berkomunikasi satu sama lain dalam konteks memecahkan masalah bisnis tertentu.

Dan apa tantangan bisnisnya? .. Mari kita lihat contoh Vasily, kepala departemen pengembangan.
  • "Nikolai, tambalan ini membutuhkan tambalan ini hari ini!"
    Jadi, korespondensi dapat dilakukan dalam konteks dokumen .
  • "Kolya, pergi ke DotA di malam hari?"
    Artinya, bahkan dengan sepasang lawan bicara, komunikasi pada saat yang sama dapat dilakukan pada topik yang berbeda .
  • "Peter, Nikolai, lihat lampiran harga di server baru."
    Jadi, satu pesan dapat memiliki beberapa penerima . Dalam hal ini, pesan mungkin berisi file yang dilampirkan .
  • "Semyon, dan kamu juga terlihat."
    Dan harus memungkinkan untuk mengundang anggota baru ke dalam korespondensi yang ada.

Marilah kita memikirkan daftar kebutuhan "jelas" ini.
Tanpa pemahaman tentang penerapan tugas dan kendala yang ditetapkan olehnya, praktis tidak mungkin untuk merancang skema basis data yang efektif untuk menyelesaikannya.

Langkah 2: Logika Minimum


Sejauh ini, semuanya ternyata sangat mirip dengan korespondensi email - alat bisnis tradisional. Jadi ya, "secara algoritmik", banyak tugas bisnis yang mirip satu sama lain, dan oleh karena itu alat untuk menyelesaikannya akan serupa secara struktural.

Mari kita perbaiki diagram logis yang dihasilkan dari hubungan entitas. Untuk mempermudah memahami model kami, kami akan menggunakan opsi yang paling primitif untuk menampilkan model ER tanpa komplikasi dari notasi UML atau IDEF:



Dalam contoh kami, orang, dokumen, dan "badan" biner file adalah entitas "eksternal" yang secara independen ada tanpa layanan kami. Oleh karena itu, kami hanya akan melihatnya di masa mendatang sebagai beberapa tautan β€œdi suatu tempat” oleh UUID.
Gambar diagram sesederhana mungkin - sebagian besar dari mereka yang Anda tunjukkan tidak ahli dalam membaca UML / IDEF. Tapi - pastikan untuk menggambar.

Langkah 3: buat sketsa struktur tabel


Tentang nama tabel dan bidang
Nama "Rusia" bidang dan tabel dapat diperlakukan berbeda, tetapi ini masalah selera. Karena kami tidak memiliki pengembang asing di "Tensor" , dan PostgreSQL memungkinkan kami untuk memberi nama bahkan dengan hieroglif, jika mereka terlampir dalam tanda kutip , kami lebih suka memberi nama objek dengan jelas, jelas, sehingga tidak ada kesalahpahaman.

Karena banyak orang menulis pesan sekaligus, beberapa dari mereka dapat melakukan ini secara offline , opsi termudah adalah menggunakan UUID sebagai pengidentifikasi tidak hanya untuk entitas eksternal, tetapi juga untuk semua objek di dalam layanan kami. Selain itu, mereka dapat dihasilkan bahkan di sisi klien - ini akan membantu kami untuk mendukung pengiriman pesan dengan akses jangka pendek dari database, dan kemungkinan benturan sangat kecil.

Struktur kasar tabel dalam database kami akan terlihat seperti ini:
Tabel: RU
CREATE TABLE ""( "" uuid PRIMARY KEY , "" uuid , "" text ); CREATE TABLE ""( "" uuid PRIMARY KEY , "" uuid , "" uuid , "" timestamp , "" text ); CREATE TABLE ""( "" uuid , "" uuid , PRIMARY KEY("", "") ); CREATE TABLE ""( "" uuid PRIMARY KEY , "" uuid , "BLOB" uuid , "" text ); 

Tabel: EN
 CREATE TABLE theme( theme uuid PRIMARY KEY , document uuid , title text ); CREATE TABLE message( message uuid PRIMARY KEY , theme uuid , author uuid , dt timestamp , body text ); CREATE TABLE message_addressee( message uuid , person uuid , PRIMARY KEY(message, person) ); CREATE TABLE message_file( file uuid PRIMARY KEY , message uuid , content uuid , filename text ); 

Cara termudah untuk mendeskripsikan formatnya adalah dengan mulai "melepaskan" grafik tautan dari tabel yang tidak merujuk ke siapa pun.

Langkah 4: Menemukan Persyaratan yang Tidak Jelas


Itu saja, kami telah merancang basis tempat Anda dapat menulis dan membaca.

Mari kita menempatkan diri pada posisi pengguna layanan kita - apa yang ingin kita lakukan dengannya?

  • Posting Terbaru
    Ini adalah daftar pesan "saya" yang secara kronologis diurutkan berdasarkan berbagai karakteristik. Di mana saya adalah salah satu penerima, di mana saya adalah penulis, di mana mereka menulis kepada saya, tetapi saya tidak menjawab, di mana mereka tidak menjawab saya ...
  • Koresponden
    Siapa yang terlibat dalam obrolan yang sangat lama ini?

Struktur kami memungkinkan kami untuk menyelesaikan kedua masalah ini "secara umum", tetapi dengan cepat - tidak. Masalahnya adalah bahwa untuk menyortir sebagai bagian dari tugas pertama, tidak mungkin untuk membuat indeks yang cocok untuk masing-masing peserta (dan Anda harus mengambil semua catatan), dan untuk menyelesaikan yang kedua, Anda perlu mengambil semua semua pesan pada topik.
Tugas pengguna yang tidak diantisipasi dapat mengakhiri produktivitas .

Langkah 5: Denormalisasi yang Wajar


Kedua masalah kami akan membantu menyelesaikan tabel tambahan, di mana kami akan menduplikasi sebagian data yang diperlukan untuk membentuk indeks yang sesuai untuk masalah kami.


Tabel: RU
 CREATE TABLE ""( "" uuid , "" smallint , "" timestamp , "" uuid , PRIMARY KEY("", "", "") ); CREATE INDEX ON ""("", "", "" DESC); CREATE TABLE ""( "" uuid , "" uuid , PRIMARY KEY("", "") ); 

Tabel: EN
 CREATE TABLE message_registry( owner uuid , registry smallint , dt timestamp , message uuid , PRIMARY KEY(owner, registry, message) ); CREATE INDEX ON message_registry(owner, registry, dt DESC); CREATE TABLE theme_participant( theme uuid , person uuid , PRIMARY KEY(theme, person) ); 

Di sini kami telah menerapkan dua pendekatan khas yang digunakan untuk membuat tabel tambahan:

  • Catatan Penggandaan
    Kami membentuk beberapa catatan sumber sekaligus dari satu catatan sumber pesan ke berbagai jenis register untuk pemilik yang berbeda - baik untuk pengirim dan penerima. Tetapi masing-masing pendaftar sekarang terletak pada indeks - karena dalam kasus khas kita hanya ingin melihat halaman pertama.
  • Rekam Unikisasi
    Setiap kali Anda mengirim pesan dalam topik tertentu, cukup untuk memeriksa apakah entri tersebut sudah ada. Jika tidak, tambahkan ke "kamus" kami.

Pada bagian selanjutnya dari artikel ini, kita akan membahas implementasi bagian dalam struktur basis data kita.

Source: https://habr.com/ru/post/id483176/


All Articles