为了设计一个能够高效获取用户所有发送和接收会话信息的聊天系统,我建议采用以下表结构设计方案:
CREATE TABLE users (
user_id BIGINT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_active TIMESTAMP,
status ENUM('online', 'offline', 'away')
);
CREATE TABLE conversations (
conversation_id BIGINT PRIMARY KEY,
conversation_type ENUM('private', 'group') NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_message_id BIGINT,
last_message_time TIMESTAMP
);
CREATE TABLE conversation_participants (
participant_id BIGINT PRIMARY KEY,
conversation_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
left_at TIMESTAMP NULL,
unread_count INT DEFAULT 0,
FOREIGN KEY (conversation_id) REFERENCES conversations(conversation_id),
FOREIGN KEY (user_id) REFERENCES users(user_id),
UNIQUE KEY (conversation_id, user_id)
);
CREATE TABLE messages (
message_id BIGINT PRIMARY KEY,
conversation_id BIGINT NOT NULL,
sender_id BIGINT NOT NULL,
content TEXT,
content_type ENUM('text', 'image', 'video', 'file') DEFAULT 'text',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
status ENUM('sent', 'delivered', 'read') DEFAULT 'sent',
FOREIGN KEY (conversation_id) REFERENCES conversations(conversation_id),
FOREIGN KEY (sender_id) REFERENCES users(user_id)
);
CREATE TABLE message_reads (
read_id BIGINT PRIMARY KEY,
message_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
read_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (message_id) REFERENCES messages(message_id),
FOREIGN KEY (user_id) REFERENCES users(user_id),
UNIQUE KEY (message_id, user_id)
);
分表策略:
索引设计:
缓存层:
SELECT c.*, m.content AS last_message, m.created_at AS last_message_time
FROM conversations c
JOIN conversation_participants cp ON c.conversation_id = cp.conversation_id
LEFT JOIN messages m ON c.last_message_id = m.message_id
WHERE cp.user_id = ? AND cp.left_at IS NULL
ORDER BY c.last_message_time DESC;
SELECT m.*, u.username AS sender_name
FROM messages m
JOIN users u ON m.sender_id = u.user_id
WHERE m.conversation_id = ?
ORDER BY m.created_at ASC;
SELECT conversation_id, COUNT(*) AS unread_count
FROM messages m
WHERE m.conversation_id IN (
SELECT conversation_id
FROM conversation_participants
WHERE user_id = ?
)
AND m.created_at > (
SELECT MAX(read_at)
FROM message_reads
WHERE user_id = ? AND message_id IN (
SELECT message_id
FROM messages
WHERE conversation_id = m.conversation_id
)
)
AND m.sender_id != ?
GROUP BY conversation_id;
这种设计既保证了数据完整性,又能高效查询用户的所有发送和接收的会话信息。