Skip to content

Latest commit

 

History

History
109 lines (86 loc) · 7.13 KB

index.md

File metadata and controls

109 lines (86 loc) · 7.13 KB

nt_msg.db — 消息数据库

nt_msg.db 是 NTQQ 存贮聊天记录本体的数据库:消息行、会话列表、未读状态都在这里。 本栏目的内容全部由 WeQ 依据自己的解析实现手写维护。

表一览

表 内容 文档
c2c_msg_table 好友单聊消息 消息行
group_msg_table 群聊消息(结构同 c2c,多 40062 贴表情列) 消息行 · 40062
dataline_msg_table 数据线消息(我的手机 / 电脑 / 平板,结构同 c2c) 消息行
recent_contact_v3_table 会话列表 recent-contact
recent_contact_top_table 置顶会话 recent-contact-top
hidden_session_storage_table_v1 隐藏会话 hidden-session
recent_contact_delete_storage 删除会话 deleted-session
msg_unread_info_table 未读信息 + 提醒高亮 unread-info
nt_uid_mapping_table uid ↔ uin ↔ sortNo 目录 下见
draft_storage_table_v1 草稿:输入了但还没点发送的内容(WeQ 读写) draft-storage

消息行

三张消息表的列布局完全一致,差别只在会话分区键(c2c 按 sortNo 分区、群按群号)。 逐列的字段表见 消息行解析;一行里最复杂的几个列:

列 名称 结构 说明
40800 消息正文(MsgBody) repeated ElementWire 一条消息的富文本消息段序列,见 40800 解析
40801 消息装扮信息 MsgDressBody 气泡 / 聊天字体 / 挂件等装扮信息,见 40801 解析
40900 消息缓存(MsgCache) repeated MsgCache(可递归嵌套) 转发/引用时缓存的源消息快照,见 40900 解析
40062 贴表情(仅群聊) repeated EmojiSticker 群消息上的表情回应,见 40062 解析

📖 建议先读 40800 解析 的前半部分 —— 「扁平信封」与「文件族共用字段」 两节是理解所有消息段的前提,各消息段文档不再重复这些内容。

nt_uid_mapping_table

账号级的身份目录,三列:

列 含义
48901 sortNo —— 该账号给每个交互过的对端分配的 1 起递增小整数
48902 uid —— 其它地方通用的不透明对端标识
1002 uin —— 对端 QQ 号

它之所以重要:c2c_msg_table 的会话分区列是 40027(= 这里的 sortNo), 所有有用的复合索引都建在它上面((40027,40003) 等);而应用层是按 uid 找会话的, 40021 恰恰没有索引。所以走快路径查 c2c 消息,必须先 uid → sortNo 翻译一次。 这张表很小且稳定,WeQ 在会话启动时整表读进内存(UidMap)常驻。

WeQ 建的派生索引

QQ 给两张消息表建的复合索引全部以会话键打头((40027,40003)、(40027,40058)…)。 这对「按会话翻消息」是够的,但跨全库、按时间窗的统计(年度报告)一条都用不上 —— 只能全表扫描并回表。WeQ 因此在开账号后于后台就地补两个覆盖索引:

索引名 表 列 服务于
weq_annual_sendtime_dir_group group_msg_table (40050,40040) 年度报告第一页 / 历史以来的方向计数
weq_annual_sendtime_dir_c2c c2c_msg_table (40050,40040) 同上(私聊侧)

过滤列(sendTime)与取值列(sentSource)都在索引里,查询退化成一次索引区间扫描, 不再碰表本体(实测 200 万行 / 2GB:0.9s → 0.06s)。这与搜索的 FTS 索引 不是一回事:那个是内容副本 + 倒排,只能落在 WeQ 自己的派生库里;这两个是就地 CREATE INDEX 的普通 B-tree,SQLite 自己维护,QQ 写入时自动更新,WeQ 没有任何 同步逻辑。

与 QQ 共存的实测结论:schema 只多出两个 index 对象、表结构不动,PRAGMA integrity_check 照常 ok,QQ 运行中 INSERT / UPDATE / DELETE 后索引即时一致; PRAGMA schema_version 会 +1,但那是 SQLite 每次 DDL 的正常行为,不是 QQ 的校验 指纹(QQ 自己也在持续改它)。代价是每次写入的一点写放大(30 万行插入 1.12s → 1.25s) 与索引占用的空间(约表体的 1–2%)。

与防撤回一样,这属于「WeQ 往 QQ 的实时库里写 DDL」。 只对实时账号生效;导入的静态备份(PC 快照 / 手机备份)不写,保持原样。


消息段(Element)索引

40800 由若干消息段(Element)组成,每段以 elementType 区分类型。各类型的字段解析见下; 未观测到的 elementType(12/13/15/17/18/19/20/22/24/25/29/43/44)不单独成篇, 完整枚举见 40800 解析 · elementType 全表。

elementType 名称 文档
1 文本 / @ text
2 图片 pic
3 文件 file
4 语音 ptt
5 视频 video
6 系统表情 face
7 回复引用 reply
8 灰字提示 gray-tip
9 红包 / 转账 wallet
10 ARK 卡片 ark
11 商城表情 mface
14 Markdown markdown
16 合并转发 multi-msg
21 通话记录 call
23 在线文件 online-file
26 空间动态提示 qq-dynamic
27 弹射表情 emoji-bounce
28 位置共享 仅一个字段,见 40800 解析
30 在线文件夹 online-folder

← 返回数据库分析