宝鸡市网站建设_网站建设公司_全栈开发者_seo优化
2025/12/25 22:10:55 网站建设 项目流程

问题背景

做一个数据库表查看、标注与分析的功能。

\(Table\)是数据库1中的表的信息(information_schema.tables);\(Documentation\)\(Table\)的数据字典文档,存储在本地文件中;\(Annotation\)是对\(Table\)的额外标注信息,存储在数据库2中。每一条\(Table\),最多关联到一条\(Documentation\)和一条\(Annotation\)

现在想搜索\(Table\)。前端向后端提供3个参数,搜索关键词列表、当前页码、每页条数;后端的搜索逻辑是,如果一条完整数据(\(Table\)+\(Documentation\)+\(Annotation\))包含所有搜索关键词,则将\(Table\)加入搜索结果中。

\(Table\)的数量目前为6000+,要做到秒级搜索。

第一版实现

因为跨数据源,所以不能简单连表查询。

对于每个\(Table\),查出\(Documentation\)\(Annotation\),然后将\(Table\)\(Documentation\)\(Annotation\)中要搜索的字段值取出来,用空格隔开拼接为字符串,形如"Table字段值 Documentation字段值 Annotation字段值",我们称之为\(SearchKey\)(搜索键)。如果每个关键词都包含在\(SearchKey\)中,则将\(Table\)加入搜索结果。

搜索时,先获取所有\(Table\),然后遍历每个\(Table\),获取\(SearchKey\)并判断是否加入搜索结果。

为了提高速度,用Redis缓存\(Table\)对应的\(SearchKey\)

分析数据情况:

  • \(Table\)只增、不删、不改,因此,搜索时要重新获取所有\(Table\),确保搜索到新\(Table\);不必考虑驱逐(evict)\(SearchKey\)的缓存。
  • \(Documentation\)不增、不删、不改,因此,不必考虑驱逐\(SearchKey\)的缓存。
  • \(Annotation\)增、删、改,因此,要在\(Annotation\)增、删、改之后建立、驱逐对应\(SearchKey\)的缓存,确保搜索到\(Annotation\)的最新信息。

实测结果:

  • 实现了功能,支持同时按\(Table\)\(Documentation\)\(Annotation\)的字段搜索。
  • 有性能问题,即使缓存已经全部完成,但每次搜索都要耗时30s左右,原因是6000+个\(Table\)遍历从Redis获取\(SearchKey\),每次耗时1~15ms,累计耗时长。

第二版实现

优化缓存策略。

获取所有\(Table\)后,构建\(SearchKeyMap\)\(Table\)\(SearchKey\)),然后将\(SearchKeyMap\)缓存,这样,下一次搜索时,只需要从Redis获取一次,提高传输效率。

为了确保搜索到新\(Table\),缓存\(SearchKeyMap\)时将\(Table\)列表的长度作为缓存键,如果新增了\(Table\),则\(SearchKeyMap\)不会命中缓存,会重新构建。

为了减少构建\(SearchKeyMap\)的时间,仍然保留单个\(SearchKey\)的缓存,仍然在\(Annotation\)增、删、改之后建立、驱逐单个\(SearchKey\)的缓存,但不同的是,还要同时驱逐\(SearchKeyMap\)的缓存。

实测结果:

  • 性能提升明显,在缓存全部完成的情况下,搜索耗时降至1.3s。
  • 仍然有性能问题,对一个\(Annotation\)做了增、删、改,会驱逐整个\(SearchKeyMap\)缓存,重建\(SearchKeyMap\)就又回到了遍历\(Table\)的情况,耗时30s左右。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询