Xây dựng DB cho website Hội Nhóm như Facebook
Dưới đây là thiết kế database MySQL tối ưu cho hệ thống Hội Nhóm có lưu lượng lớn, nhiều nhóm – bài viết – bình luận – thành viên, phù hợp để chạy production, dễ scale, dễ cache.
Thiết kế theo tư duy: Facebook Groups / Reddit / Zalo Group
🎯 MỤC TIÊU THIẾT KẾ
Chịu tải lớn (nhiều user online, nhiều bài viết)
Query nhanh (index hợp lý, tránh JOIN nặng)
Dễ mở rộng (sharding, cache Redis)
Phù hợp Java / Spring Boot / MyBatis / JPA
🧠 TỔNG QUAN DATABASE
` users groups group_categories (2 cấp) provinces
group_members group_posts group_post_comments group_post_likes
group_statistics (cache số liệu) `
1️⃣ BẢNG USERS (người dùng)
` CREATE TABLE users ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, email VARCHAR(120) UNIQUE, password_hash VARCHAR(255) NOT NULL, full_name VARCHAR(100), avatar_url VARCHAR(255),
status TINYINT DEFAULT 1 COMMENT '1=active,0=blocked',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_user_status (status)
) ENGINE=InnoDB; `
🔹 Tối ưu
BIGINTcho scale lớnKhông JOIN user quá sâu → chỉ lấy cần thiết
2️⃣ BẢNG PROVINCES (tỉnh / thành)
` CREATE TABLE provinces ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, slug VARCHAR(100) UNIQUE,
group_count INT DEFAULT 0 COMMENT 'cache số nhóm'
) ENGINE=InnoDB; `
🔹 group_count để không COUNT realtime
3️⃣ BẢNG GROUP_CATEGORIES (2 cấp)
` CREATE TABLE group_categories ( id INT AUTO_INCREMENT PRIMARY KEY, parent_id INT DEFAULT NULL, name VARCHAR(100) NOT NULL, slug VARCHAR(120) UNIQUE,
group_count INT DEFAULT 0,
sort_order INT DEFAULT 0,
INDEX idx_parent (parent_id)
) ENGINE=InnoDB; `
🔹 parent_id = NULL → cấp cha
🔹 Cache group_count để sidebar load nhanh
4️⃣ BẢNG GROUPS (hội nhóm)
` CREATE TABLE groups ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(150) NOT NULL, slug VARCHAR(160) UNIQUE, description TEXT, cover_image VARCHAR(255),
category_id INT NOT NULL,
province_id INT NOT NULL,
owner_id BIGINT UNSIGNED NOT NULL,
privacy TINYINT DEFAULT 1 COMMENT '1=public,2=private',
member_count INT DEFAULT 0,
post_count INT DEFAULT 0,
status TINYINT DEFAULT 1 COMMENT '1=active,0=hidden',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_category (category_id),
INDEX idx_province (province_id),
INDEX idx_created (created_at),
INDEX idx_status (status)
) ENGINE=InnoDB; `
🔥 RẤT QUAN TRỌNG
member_count,post_count→ cacheKhông COUNT trực tiếp bảng member/post
5️⃣ BẢNG GROUP_MEMBERS (thành viên nhóm)
` CREATE TABLE group_members ( group_id BIGINT UNSIGNED NOT NULL, user_id BIGINT UNSIGNED NOT NULL,
role TINYINT DEFAULT 1 COMMENT '1=member,2=admin,3=owner',
joined_at DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (group_id, user_id),
INDEX idx_user (user_id)
) ENGINE=InnoDB; `
💡 Composite PK → lookup cực nhanh
6️⃣ BẢNG GROUP_POSTS (bài viết)
` CREATE TABLE group_posts ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, group_id BIGINT UNSIGNED NOT NULL, author_id BIGINT UNSIGNED NOT NULL,
title VARCHAR(255),
content LONGTEXT,
like_count INT DEFAULT 0,
comment_count INT DEFAULT 0,
status TINYINT DEFAULT 1 COMMENT '1=public,0=hidden',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_group_time (group_id, created_at DESC),
INDEX idx_author (author_id)
) ENGINE=InnoDB; `
🔥 Index cực kỳ quan trọng
(group_id, created_at DESC)→ load newsfeed
7️⃣ BẢNG GROUP_POST_COMMENTS (bình luận)
` CREATE TABLE group_post_comments ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, post_id BIGINT UNSIGNED NOT NULL, user_id BIGINT UNSIGNED NOT NULL,
parent_id BIGINT UNSIGNED DEFAULT NULL,
content TEXT NOT NULL,
status TINYINT DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_post (post_id),
INDEX idx_parent (parent_id)
) ENGINE=InnoDB; `
🔹 Hỗ trợ reply comment (2 cấp) 🔹 Không nên quá sâu (tối ưu UI + DB)
8️⃣ BẢNG GROUP_POST_LIKES
` CREATE TABLE group_post_likes ( post_id BIGINT UNSIGNED NOT NULL, user_id BIGINT UNSIGNED NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (post_id, user_id),
INDEX idx_user (user_id)
) ENGINE=InnoDB; `
💡 Không auto increment → tránh spam like
9️⃣ BẢNG GROUP_STATISTICS (CACHE)
` CREATE TABLE group_statistics ( group_id BIGINT UNSIGNED PRIMARY KEY, daily_posts INT DEFAULT 0, weekly_posts INT DEFAULT 0, monthly_posts INT DEFAULT 0,
last_updated DATETIME
) ENGINE=InnoDB; `
🔥 Dành cho trang thống kê / ranking
⚡ TỐI ƯU HIỆU NĂNG (CỰC QUAN TRỌNG)
✅ 1. Không COUNT realtime#
❌ SELECT COUNT(*) FROM group_posts
✅ dùng post_count, member_count
✅ 2. Redis cache#
Cache:
Trang chủ
Sidebar tỉnh / thể loại
Feed nhóm
Key gợi ý:
group:{id}:posts category:{id}:groups province:{id}:groups
✅ 3. Partition (khi > 10 triệu bài)#
ALTER TABLE group_posts PARTITION BY HASH(group_id) PARTITIONS 16;
✅ 4. Chuẩn để scale Microservice#
Group Service
Post Service
User Service
🧩 QUAN HỆ SƠ ĐỒ (TÓM TẮT)
User ──< Group_Members >── Group Group ──< Group_Posts ──< Comments Group ── Category Group ── Province
Bài liên quan trong #Database
-
Hướng dẫn cài MinIO trên Ubuntu 24
minhdev -
HƯỚNG DẪN CÀI POSTGRESQL + POSTGIS TRÊN UBUNTU (FULL)
minhdev -
Những việc cần chú ý mà Lập Trình Viên cần phải biết khi làm việc với Database
topdev -
Hệ thống như thế nào thì nên sử dụng MongoDB
minhdev -
Cách kiểm tra server linux đã cài Redis chưa và cách cài nó như thế nào
minhdev