7s到65ms!记一次代码优化
2017.11.20
sherryriver
流水账技术
 pv:
几个月之前的事情,记录下。
测试反馈商品展示页偶尔加载缓慢,不加缓存第一次查询耗时达到7s左右,
通过排查发现商品详情的规格参数查询拖了后腿,这一块是调用同事写的接口,遂开始尝试代码级别优化。
原型图:
与前端约定的数据结构如下:
{ "data": [ { "specifications": "钢 银白", "stylePropretyGroupList": [ { "groupName": "机芯", "stylePropertiesList": [ { "codeName": "机芯类型", "valueName": "机械" } ] } ] } ] }
|
然后进入实现方法代码,需优化代码如下:
for (Integer productCode : productList) { DetailSpecificationInfo detailSpecificationInfo = new DetailSpecificationInfo(); Set<Integer> groupCodeSet = new HashSet<>(); ProductEntity productEntity = dao.find(ProductEntity.class, productCode); detailSpecificationInfo.setSpecifications(productEntity.getSpecifications()); StyleEntity styleEntity = dao.find(StyleEntity.class, productEntity.getStyleCode()); Integer styleCode = styleEntity.getStyleCode(); List<StylePropertyGroupInfo> stylePropretyGroupList = new ArrayList<>(); List<StylePropertiesEntity> list = jinq.stylePros().where(p -> p.getStyleCode() == styleCode).toList(); for (StylePropertiesEntity stylePropertiesEntity : list) { Integer propertyCode = stylePropertiesEntity.getPropertyCode(); ProductPropertyEntity productPropertyEntity = dao.find(ProductPropertyEntity.class, propertyCode); Integer groupCode = productPropertyEntity.getGroupCode(); groupCodeSet.add(groupCode); } for (Integer groupCode : groupCodeSet) { StylePropertyGroupInfo StylePropertyGroupInfo = new StylePropertyGroupInfo(); List<StyleProListByCodeInfo> stylePropertiesList = new ArrayList<>(); ProductPropertyGroupEntity productPropertyGroupEntity = dao.find(ProductPropertyGroupEntity.class, groupCode); StylePropertyGroupInfo.setGroupName(productPropertyGroupEntity.getGroupName()); for (StylePropertiesEntity stylePropertiesEntity : list) { Integer propertyCode = stylePropertiesEntity.getPropertyCode(); ProductPropertyEntity productPropertyEntity = dao.find(ProductPropertyEntity.class, propertyCode); Integer groupCode1 = productPropertyEntity.getGroupCode(); if (groupCode1 == groupCode) { StyleProListByCodeInfo styleProListByCodeInfo = new StyleProListByCodeInfo(); styleProListByCodeInfo.setCodeName(productPropertyEntity.getPropertyName()); styleProListByCodeInfo.setValueName(stylePropertiesEntity.getPropertyValue()); stylePropertiesList.add(styleProListByCodeInfo); } } StylePropertyGroupInfo.setStylePropertiesList(stylePropertiesList); stylePropretyGroupList.add(StylePropertyGroupInfo); } detailSpecificationInfo.setStylePropretyGroupList(stylePropretyGroupList); detailSpecificationList.add(detailSpecificationInfo); }
|
都没看完,密密麻麻头晕 (╯‵□′)╯︵┴─┴
在同事讲解原需求下开始修改代码。
约定的数据结构导致开发拼接数据难免多层循环,在循环里面调用sql查询。常见的商品属性规格表设计有2种方式,一是目前的使用方法 用关联表、二是保存json数据。目前这个方法不能盲目的改数据库表结构,而且不能破坏与前端对接的约定。
改进方案:在循环外,使用SQL一次性查询出所有必须要用到的数据,循环内不进行远程调用和SQL查询
sql部分如下
查询数据如下
然后代码优化,部分如下:
List<DetailSpecificationInfo> listInfo = new ArrayList<>(); List<GoodsPropertyExtEntity> list = dao.getPropertyByGoodsCode(goodsCode);
Map<String, DetailSpecificationInfo> map = new HashMap<>(); DetailSpecificationInfo detailSpecificationInfo; String specification;
for (GoodsPropertyExtEntity goodsPropertyExtEntity : list) { specification = goodsPropertyExtEntity.getSpecifications(); detailSpecificationInfo = map.get(specification); if (detailSpecificationInfo == null) { detailSpecificationInfo = new DetailSpecificationInfo(); detailSpecificationInfo.setSpecifications(specification); map.put(specification, detailSpecificationInfo); }
StylePropertyGroupInfo stylePropertyGroupInfo = new StylePropertyGroupInfo(); String groupName = goodsPropertyExtEntity.getGroupName(); stylePropertyGroupInfo.setGroupName(groupName);
List<StyleProListByCodeInfo> stylePropertiesList = new ArrayList<>();
StringBuilder tmp = new StringBuilder(); tmp.append(goodsPropertyExtEntity.getCodeName()); tmp.append(","); tmp.append(goodsPropertyExtEntity.getValueName()); StyleProListByCodeInfo styleProListByCodeInfo = null; String[] splitTmp = StringUtils.split(tmp.toString(), ",");
for (int i = 0; i <= splitTmp.length / 2 - 1; i++) { styleProListByCodeInfo = new StyleProListByCodeInfo(); styleProListByCodeInfo.setCodeName(splitTmp[i]); styleProListByCodeInfo.setValueName(splitTmp[splitTmp.length / 2 + i]); stylePropertiesList.add(styleProListByCodeInfo); } stylePropertyGroupInfo.setStylePropertiesList(stylePropertiesList);
detailSpecificationInfo.getStylePropretyGroupList().add(stylePropertyGroupInfo); }
listInfo.addAll(map.values()); return new ServiceResultT<>(listInfo);
|
在第二个注释处这里玩了一个小心思,codeName与valueName数据一一对应,合并起来然后二分赋值,避免了多一次循环。
最后无缓存条件下测试响应时间平均下来65ms 大功告成,哈哈哈