有这样一个场景,我有一张商家表,一个商品表,和一个商家货架表,根据门店距离升序,商品销量降序,商品价格升降序
门店信息表
距离排序需要用到 lat 和 lng 字段
门店有对应的货架数据,货架数据主要记录商品
货架表
商品表
前端查询数据有分页,每次查询数据我基本都是把全部门店信息查出来,然后循环,在查询对应的货架表在连表差商品表,然后获取销量最高的那一条商品信息。
这种方式导致,如果商品数据过多会导致接口响应时间会比较长,之前测试数据商品表300+数据接口响应大概在3s-5s左右
以下是对应接口代码代码
最后返回商品信息和对应门店信息在分页,以下是返回后的后续代码
其中 getGoodsUnavailableTime 获取商品的不可用时间,又查了一次数据库,当然这个就比较快。
getMerchants 获取商品对应的适用门店,也是查了数据库,然后里面又去查了门店的评价统计数量和门店评分
感觉如果商品数据在多点的话,查询数据库会把程序拖死,如果在来点并发就更容易噶了,想看看有没有什么好点的解决办法可以解决查询慢的问题,主要是解决慢的问题
页面展示图
不太了解商家的量级,如果量级不大可以这么来:
你最好先确认哪个sql或者哪部分逻辑处理耗时长,不太清楚你的具体业务逻辑,第一个问题是前端分页获取为什么要把所有都查出来,再有一些商品数据在这个列表要不要展示是否可以去除查询,还有就是一些像你说的销量最高这种,研究下要不要每次都查,字段维护可不可以
既然已经数组切割了进行分页返回商品信息,最后一张图的SQL应该可以提到循环前,用in查询组装之后直接再循环里面isset判断来赋值处理
初看一下《距离排序》那块,感觉有些问题啊:
好像没必要,一次性算出
50km
内商家,的所有商品,的销量?能不能根据上次分页(如
[0km, 1km)
)的最远商家(如800m
),继续找下一段距离的(如
[800m, 2km)
)商家列表,再算这批商家的销冠商品?货架表
的索引,改成site_id, show, status, goods_id
,应该能快些。因为不用每次都回表查
status
和goods_id
。另外,
status
和show
能不能合并呢。。为啥你是,按价格从高到低排,价格相同再看销量呢。。
另外,你不是取最高一条吗?怎么不数据库里排好,直接拿出来呢?
如果平均每家店有 100 个商品,你数据传输量就少 99% 啊。。
如果你
商品表
已经有《是否上架了》信息,为啥还要连货架表
呢。。是因为只有
货架表
有《是否展示》数据吗?那就像第二点说的:
后面没细看,只看了文字。
能不能在取销冠商品时,顺便也拿了呢?
同理,能不能在取商家时,顺便也拿了呢。。
商家对门店的距离是固定的,就算地址有变化可以更新,完全用一个字段或者关联表做距离数据保存。同理,销量一样可以做单独字段,不用实时去查。距离的类别,可以做距离分组来筛选,比如0到80M是一个组,80到150时一组。
可以尝试用geohash来存储位置信息,查询的时候先查询对应geohash的范围的数据,可以减少你得分页数据量,在考虑你的连表查询的索引建立,看见你得代码有好多部分可以提出来公用,同样的连表只是排序方式不同这些可以提出来,代码更加简洁
查商家和用户的距离可以用MySQL的ST_Distance_Sphere函数,就不需要查出所有的商家再计算距离
前端页面操作做修改,先请求返回门店列表,根据门店id在返回货架,同理再返回货物。。。。。
如果商品只属于一个商家,并且50km内的商家数量不是很多,可以把商家id存到商品表,sql查出按距离排序并筛选过的商家ids,假如ids=[3,2,1,5],商家不多的话不会很慢,然后商品表
WHERE 商家id in (3,2,1,5) ORDER BY FIELD(商家id, 3,2,1,5)
这种查询本来都有问题,应该将商家的经纬度数据放到商品表上,或者商品表为主表left join 商家 先根据经纬度算距离排序,在根据商品销量(每次购买商品对商品进行记录)排序,在根据价格排序 其次如果用户登录了在加个缓存
用搜索引擎可能更好点,如果数据没多少不需要搜索引擎,可以尝试把数据拉平; 新建一张搜索表,保存纬度、商品销量、价格等数据,用来搜索; 这样只需要一条sql就行了,查出来的数据再把需要的数据给拼上
我们是这么干的,数据不多的话可以试
这里 N+1 了,肯定慢,你300个商品,这块就执行了300次查询
个人推荐使用搜索引擎,后续扩展性高一些。
看看遍历里的查询能不能提到循环外一次性查结果,后面再组装数据
建张新的表,将所有要查询和排序的条件都加上;