系统设计 --- MongoDB亿级数据查询优化策略

发布于:2025-06-13 ⋅ 阅读:(19) ⋅ 点赞:(0)

系统设计 --- MongoDB亿级数据查询分表策略

背景

使用audit log实现Audi Trail功能

  • Audit Trail范围: 六个月
  • 数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据
  • 需要实现全文检索
  • 按照时间倒序
  • 因为license问题,不能使用ELK只能使用MongoDB
  • 理想情况下,对于大量数据的全字段全文检索查询的最佳方案是ELK

挑战

  • 要求一分钟之内前端返回结果
  • 需要支持不同的查询条件
  • 需要支持服务器端分页
  • 需要支持服务器端排序(时间排序)

Mongo性能验证:

  • Mongo单个Collection可支持500w条数据,超过500w条时,查询速度会变慢甚至超时(一分钟)

Solution — 分表

如何进行分表

  • 因为是按照时间排序,所以可以按照数据的时间进行分表
  • 一周的数据放进一个collection (一周的数据大概是300万-400万,刚好在500w的阈值之内)

如何写入

  • 实现一个映射方法:输入一个年月日的时间可以映射成一个字符串, 使用这个字符串作为collection的名字
  • Map(2025-01-05) = "2025_Week_1"

如何进行分页查询:

查询条件: pageSize = 100, pageNum = 2, startTime = 2024-06-08, endTime = 2024-10-10, operator = "Daniel" and message conatines "XYC"

step1: count (very expensive)

  • 根据查询的起止时间,得到涉及哪些collections, for example
  • collection1 (50条)
  • collection 2 (60条)
  • collection 3 (110条)
  • collection 4 (20条)
  • collection 5 (0条)
  • 这里可以优化,把相同查询条件的count缓存起来
  • 比如用户在前端点击下一页时往往使用的是同样的查询条件

step2: 查询

  • 并发查询每个collection有多少符合条件的数据 (也就是operator = “Daniel” and message conatines “XYC”`)
  • 根据paging的信息,计算出需要取多少数据,并进行抓取
  • `pageSize = 100, pageNum = 2
  • collection1 (50条)跳过
  • collection 2 (60条) 跳过50条,抓取后10条
  • collection 3 (40条) 抓取40条
  • collection 4 (20条) 抓取10条

数据库交互次数

  • 两次:count一次,实际查询一次