记一次 base64 图片存储引发后端查询接口性能断崖式下降问题全程解析
时间:2022-07-23
本文章向大家介绍记一次 base64 图片存储引发后端查询接口性能断崖式下降问题全程解析,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
问题回顾
同事小赵接到客户导入新闻数据要求,由客户提供新闻数据。于是,小赵通过 SQL 脚本入库新闻数据后,发现前台展示新闻特别慢。幸好是晚上凌晨 1 点,用户比较少,处理问题来得及,最终经过一个小时排查问题,原来问题出在这里。。。
问题定位
在小赵导完数据后,测试小赵发现内容管理列表页访问特别慢,加载完数据需要 16 秒左右。
于是我用 F12 打开 chrome 调试工具,发现获取新闻内容列表数据的 API 接口:“getManageArticleList" 接收的数据有 7.1 M,接口响应时间长达 16 秒多,太不正常了。
但是同一个接口换一个查询条件,接收的数据只有 367 KB,响应时间 4.5 秒。
由此,这说明两个问题
第一、API 接口的请求与响应是没问题的
第二、换查询条件后,接口响应时间差距近 12 秒之多,说明接收数据有问题
既然是数据问题,于是在和小赵对比入库前和入库后的新闻数据后,发现问题出在图片 base64 加密存储。
原来,客户提供的文章数据中包含图片,但由于客户原图不在了,只能从别的地方收集新闻时,把包含图片的新闻采用了 base64 加密串给了小赵。这些 base64 加密的图片每张基本上在 1 M 左右,前端一次性分页加载 10 条共 7M 的数据,变慢就不足为怪了。
另外,为什么新闻列表页需要加载图片呢?通过代码走查,发现图片是放在 contentText 字段里面,但是 新闻内容列表
select 分页语句却包含了 contentText 字段,明显 select 语句不合理。
select ..., contenText from article
解决方案
由于时间比较紧迫,本次发版又不涉及服务升级,只能从修改数据入手了。
第一步,用 like 模糊查询存在包含 base64 串的文章,共 34 条记录,数据比较少
select id,title,contenText from article where contenText like '%data:image%'
第二步, 从新闻详情页下载图片,用 fastdfs 分布式文件服务器上传图片后,得到图片的下载地址,替换 img 标签的 src 属性值,格式如下:
group1/M00/00/00/rBIK6VcaP0aARXDSNFHrUgHEviQ663.jpg
10 个人 34 条新闻,花了近 20 分钟,完成 base64 图片地址替换后,问题解决。
base64 编码原理
简单来说就是把一张图片数据加密成一个字符串,使用该字符串代替图像地址,这样的好处是不需要单独用文件服务器存储文件。
问题总结
有时候,问题就出在最显眼的问题描述上,需要有心人去细细琢磨。另外,其实大部分问题都可以在官网上找到相关技术解决方案,却又苦于受英语单词的折磨。
- NBitcoin:最完整的比特币港口(第1部分:加密)
- 【定制化图像开放平台】入门实例之手写数字模型训练
- 【人工智能】动物、植物、车型、菜品、LOGO识别示例代码
- 【大牛经验】写好Java代码的30条经验总结
- 乐视网面试真题,非一般的题目
- 数据挖掘算法-python实现:Logical回归
- 提取数字——字符串、正则面试题
- 【盟友分享】如何快速获取Chromium源码和编译
- .NET中的密钥加密
- 数据挖掘工程师笔试及答案
- 各大公司移动端页面 - 导航的实现
- JavaScript 运行机制之执行顺序详解
- Math对象面试题目
- Highcharts AJAX JSON JQuery 实现动态数据交互显示图表 柱形图
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 多线程基础(七):关于HotSpot中notify方法不具备随机性的证明
- Day18:二叉树的镜像
- ksubdomain 无状态域名爆破工具
- Day19:顺时针打印矩阵
- 疑似 KimsukyAPT 组织最新攻击活动样本分析
- 查找被删除但仍然占据磁盘的文件
- WPF 获取本机所有字体拿到每个字符的宽度和高度
- WPF 自己封装 Skia 差量绘制控件
- C# dotnet 使用 OpenXml 解析 Word 文件
- Day20:包含min函数的栈
- No module named ‘SerialClient‘和Cannot import package : rosserial_arduino
- 提升开发效率N倍的20+命令行神器!(附 demo)
- Java反射原理
- 【每日一题】46. Permutations
- 免费下论文的10个方法