Skip to content

数据库 Schema

IM 系统使用 SQLite 作为数据存储,通过 sql.js(WebAssembly)运行,无需安装额外数据库服务。

表结构总览

表名说明主键
users用户信息id
groups群聊信息id
group_members群成员关系(group_id, user_id)
messages消息记录id
friends好友关系(user_id, friend_id)
friend_requests好友请求id
push_subscriptions推送订阅user_id
unread_counts未读计数(user_id, chat_id)
blocked_users黑名单(user_id, blocked_id)
config系统配置key

users — 用户表

sql
CREATE TABLE IF NOT EXISTS users (
    id TEXT PRIMARY KEY,
    username TEXT NOT NULL,
    avatar TEXT,
    password TEXT NOT NULL DEFAULT '',
    nickname TEXT,
    email TEXT,
    created_at INTEGER,
    updated_at INTEGER,
    push_enabled INTEGER DEFAULT 1,
    dnd_enabled INTEGER DEFAULT 0,
    gender TEXT DEFAULT '',
    bio TEXT DEFAULT '',
    phone TEXT DEFAULT ''
);
字段类型说明
idTEXT用户唯一 ID(UUID)
usernameTEXT登录账号(唯一,2-32 字符)
avatarTEXT头像 URL
passwordTEXT密码(bcrypt 加密)
nicknameTEXT昵称(最长 64 字符)
emailTEXT邮箱(最长 128 字符)
created_atINTEGER创建时间戳(毫秒)
updated_atINTEGER更新时间戳(毫秒)
push_enabledINTEGER是否启用推送:0=关闭,1=开启
dnd_enabledINTEGER是否免打扰:0=关闭,1=开启
genderTEXT性别
bioTEXT个性签名(最长 500 字符)
phoneTEXT手机号(最长 20 字符)

索引idx_users_username ON users (username)


groups — 群聊表

sql
CREATE TABLE IF NOT EXISTS groups (
    id TEXT PRIMARY KEY,
    name TEXT NOT NULL,
    creator_id TEXT NOT NULL,
    create_time INTEGER NOT NULL,
    announcement TEXT DEFAULT '',
    avatar TEXT DEFAULT '',
    description TEXT DEFAULT ''
);
字段类型说明
idTEXT群唯一 ID
nameTEXT群名称(最长 64 字符)
creator_idTEXT群主用户 ID
create_timeINTEGER创建时间戳(毫秒)
announcementTEXT群公告(最长 2000 字符)
avatarTEXT群头像 URL
descriptionTEXT群描述(最长 500 字符)

group_members — 群成员表

sql
CREATE TABLE IF NOT EXISTS group_members (
    group_id TEXT,
    user_id TEXT,
    join_time INTEGER NOT NULL,
    role TEXT DEFAULT 'member',
    is_muted INTEGER DEFAULT 0,
    PRIMARY KEY (group_id, user_id)
);
字段类型说明
group_idTEXT群 ID
user_idTEXT用户 ID
join_timeINTEGER加入时间戳(毫秒)
roleTEXT角色:creatoradminmember
is_mutedINTEGER是否被禁言:0=否,1=是

索引idx_group_members_user ON group_members (user_id)


messages — 消息表

sql
CREATE TABLE IF NOT EXISTS messages (
    id TEXT PRIMARY KEY,
    from_id TEXT NOT NULL,
    to_id TEXT NOT NULL,
    type TEXT NOT NULL,
    content TEXT NOT NULL,
    timestamp INTEGER NOT NULL,
    content_type TEXT DEFAULT 'text',
    reply_to TEXT DEFAULT '',
    is_revoked INTEGER DEFAULT 0,
    image_url TEXT DEFAULT ''
);
字段类型说明
idTEXT消息唯一 ID(客户端生成的 UUID)
from_idTEXT发送者用户 ID
to_idTEXT接收者 ID(用户 ID 或群 ID)
typeTEXT消息类型:single(私聊)或 group(群聊)
contentTEXT消息内容(最长 10000 字符)
timestampINTEGER发送时间戳(毫秒)
content_typeTEXT内容类型:textimage
reply_toTEXT回复的消息 ID(空字符串表示非回复)
is_revokedINTEGER是否已撤回:0=否,1=是
image_urlTEXT图片 URL(contentType 为 image 时使用)

索引

索引名字段用途
idx_messages_from_to(from_id, to_id)查询两人之间的消息
idx_messages_to(to_id)查询发给某人的消息
idx_messages_timestamp(timestamp)按时间排序
idx_messages_to_ts(to_id, timestamp)查询某会话的消息(按时间)
idx_messages_from_to_ts(from_id, to_id, timestamp)精确查询两人消息(按时间)

friends — 好友关系表

sql
CREATE TABLE IF NOT EXISTS friends (
    user_id TEXT,
    friend_id TEXT,
    create_time INTEGER NOT NULL,
    PRIMARY KEY (user_id, friend_id)
);

双向存储

好友关系为双向存储:A 添加 B 为好友时,同时插入 (A, B)(B, A) 两条记录。


friend_requests — 好友请求表

sql
CREATE TABLE IF NOT EXISTS friend_requests (
    id TEXT PRIMARY KEY,
    from_id TEXT NOT NULL,
    to_id TEXT NOT NULL,
    status TEXT NOT NULL,
    create_time INTEGER NOT NULL
);
字段类型说明
idTEXT请求唯一 ID
from_idTEXT发起者用户 ID
to_idTEXT接收者用户 ID
statusTEXT状态:pending(待处理)、accepted(已接受)、rejected(已拒绝)
create_timeINTEGER创建时间戳(毫秒)

索引

索引名字段
idx_friend_requests_to(to_id, status)
idx_friend_requests_from(from_id, status)

push_subscriptions — 推送订阅表

sql
CREATE TABLE IF NOT EXISTS push_subscriptions (
    user_id TEXT PRIMARY KEY,
    subscription TEXT NOT NULL
);
字段类型说明
user_idTEXT用户 ID(每个用户最多一条订阅)
subscriptionTEXTPushSubscription 对象的 JSON 字符串

unread_counts — 未读计数表

sql
CREATE TABLE IF NOT EXISTS unread_counts (
    user_id TEXT NOT NULL,
    chat_id TEXT NOT NULL,
    chat_type TEXT NOT NULL,
    count INTEGER DEFAULT 0,
    PRIMARY KEY (user_id, chat_id)
);
字段类型说明
user_idTEXT用户 ID
chat_idTEXT聊天对象 ID(私聊为对方用户 ID,群聊为群 ID)
chat_typeTEXTsinglegroup
countINTEGER未读消息数

索引idx_unread_user ON unread_counts (user_id)


blocked_users — 黑名单表

sql
CREATE TABLE IF NOT EXISTS blocked_users (
    user_id TEXT NOT NULL,
    blocked_id TEXT NOT NULL,
    create_time INTEGER NOT NULL,
    PRIMARY KEY (user_id, blocked_id)
);

config — 系统配置表

sql
CREATE TABLE IF NOT EXISTS config (
    key TEXT PRIMARY KEY,
    value TEXT NOT NULL
);

存储系统级配置项,如 single_sign_on 等。


数据库优化

WAL 模式

服务启动时自动开启 WAL(Write-Ahead Logging)模式,允许读写并发执行,显著提升并发性能。

防抖写入

写操作不是立即持久化到磁盘,而是先缓存在内存中,100ms 防抖后批量写入。服务关闭时执行 forceSave 确保数据完整。

索引策略

共 10 个索引,覆盖主要查询路径:

索引优化场景
idx_messages_from_tomessages查询两人聊天记录
idx_messages_tomessages查询发给某人的消息
idx_messages_timestampmessages按时间排序
idx_messages_to_tsmessages会话消息分页查询
idx_messages_from_to_tsmessages精确两人消息分页
idx_users_usernameusers按用户名查找
idx_friend_requests_tofriend_requests查询收到的好友请求
idx_friend_requests_fromfriend_requests查询发出的好友请求
idx_unread_userunread_counts查询用户未读计数
idx_group_members_usergroup_members查询用户加入的群