背景,一个详情接口(需要主单和子单里面的sku信息和store门店信息),执行时间大概30秒左右,时间太长了
表结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | create table adjust_price (     id              bigint unsigned auto_increment         primary key,     name            varchar(20)  default '' not null comment '调价单名称',     start_at        datetime                null comment '调价开始时间',     end_at          datetime                null comment '调价结束时间',     description     varchar(500) default '' not null comment '调价单描述',     sell_channel_id int unsigned default 0  not null comment '销售渠道id',     create_by       int unsigned default 0  not null comment '创建人',     update_by       int unsigned default 0  not null comment '更新人',     created_at      timestamp               null,     updated_at      timestamp               null,     deleted_at      timestamp               null )     comment '调价单主表' collate = utf8mb4_unicode_ci;
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | create table adjust_price_product_sku_store (     id              bigint unsigned auto_increment         primary key,     adjust_price_id int unsigned   default 0    not null comment '调价单id',     sell_channel_id int unsigned   default 0    not null comment '销售渠道id',     sku_id          int unsigned   default 0    not null comment '渠道skuId',     promotion_price decimal(10, 2) default 0.00 not null comment '促销价',     store_id        int unsigned   default 0    not null comment '门店id',     start_at        datetime                    null comment '调价开始时间',     end_at          datetime                    null comment '调价结束时间',     created_at      timestamp                   null,     updated_at      timestamp                   null,     deleted_at      timestamp                   null )     comment '调价单子表' collate = utf8mb4_unicode_ci;
 
 
  | 
 
常规做法
skuId数量M = 100, storeId的数量N = 450,做笛卡尔积组合,那么子表adjust_price_product_sku_store每次插入的数据会有 M*N条,大概45000条。如果使用Laravel框架,detail 接口常规做法,通过做法通过with把子表带出来
1 2
   | AdjustPrice::whereId($id)->with(['adjustPriceStoreGroup', 'adjustPriceProductSkuStore'])->first();
 
 
  | 
 
但是,这样带出的主子表数据会特别多,数据大小大概11Mb,执行时间大概10s,外加一些逻辑处理接口的整体响应时间大概25s左右,用户体验特别不好。优化思路:将子表的数据数量级进行降级处理,把 M*N 的数量级,变成 M+N 的数量级
优化做法
- 查询某个调价单 
adjust_price 第一条子表的数据 adjust_price_product_sku_store 
1 2 3 4
   | $adjustPriceProductSkuStore = app(AdjustPriceProductSkuStoreRepository::class)->getByAdjustPriceIdLimitOne($adjustPrice->id);
 
  select sku_id, store_id from adjust_price_product_sku_store limit 1;
 
  | 
 
1 2 3 4 5 6 7 8
   |  $adjustPriceProductSkuStoresToGetStoreIds = app(AdjustPriceProductSkuStoreRepository::class)->list([     'adjustPriceId' => $adjustPrice->id,     'skuId'         => $adjustPriceProductSkuStore->sku_id, ]);
  $storeIds = collect(adjustPriceProductSkuStoresToGetStoreIds)->plick('store_id')->toArray();
 
 
  | 
 
最终效果:
1 2
   | 时间从  20 秒 降到了 1秒 数据从11Mb 降到了 400Kb
 
  | 
 
20211209 数据设计修改
原来的数据库设计在skuId和storeId数据量不大的时候还是可行的,但是数据量大的时候,性能瓶颈很快就出现了,故重新修改数据库设计,将上面的 adjust_price_product_sku_store,分拆成2个表 adjust_price_product_sku 和 adjust_price_store,在数据库层直接把 M*N 的关系变成 M+N 的关系。接口响应时间都可以控制在1秒以内,5年内应该不会出现性能问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | create table adjust_price_product_sku (     id              bigint unsigned auto_increment         primary key,     adjust_price_id int unsigned   default 0    not null comment '调价单id',     sku_id          int unsigned   default 0    not null comment '渠道skuId',     promotion_price decimal(10, 2) default 0.00 not null comment '促销价',     start_at        datetime                    null comment '调价开始时间',     end_at          datetime                    null comment '调价结束时间',     created_at      timestamp                   null,     updated_at      timestamp                   null,     deleted_at      timestamp                   null )     collate = utf8mb4_unicode_ci;
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | create table adjust_price_store (     id              bigint unsigned auto_increment         primary key,     adjust_price_id int unsigned default 0 not null comment '调价单id',     store_id        int unsigned default 0 not null comment '门店id',     start_at        datetime               null comment '调价开始时间',     end_at          datetime               null comment '调价结束时间',     created_at      timestamp              null,     updated_at      timestamp              null,     deleted_at      timestamp              null )     comment '调价单sku子表' collate = utf8mb4_unicode_ci;
 
 
 
  |