最近碰到一个业务排序要求,多家供应商提供相似的商品 但可能折扣不一样,折扣也至少有 2 种,一个是当前供应商的通用折扣作用于它的所有商品,还有另一种比如不同重量区间(重量越大折扣越少,甚至加价)设置不同的折扣,比如商品重量在 20 - 30 重量单位的 9 折,40 - 50 重量单位之间的 95 折,300 以上的 重量单位的可能是加价 15%。
现在搜索时符合条件的数据要按折后价排序后分页显示。
这个查询本身还有 7 ,8 个 过滤条件可选,比如颜色,形状等。 商品不会频繁修改,可以多加些索引。老板还说客户可以不输入任何限制条件。商品的规模 暂时估计 总共 1 千万,一个供应商的商品估计不超过 50 万。
因为要实时计算价格再排序的话,会影响性能,那个重量范围还要联表查询得到区间折扣率,所有数据 MySQL 要立即先计算一次才能比较价格,换个思路,如果事先把价格转换成折后价 避免查询时临时计算价格,如果供应商级别修改了折扣率,最多的可能有几十万个商品都要受影响,在后台换算成折后价的话,会有生效的延迟,全部更新完之前客户查询时排序结果就不正确。
大家说说,这个怎么处理比较好。

考虑影响价格的因素? 比如:重量越大折扣越少 => 重量和价格成正比,重量的顺序就是价格的顺序?我能想到的, 不知道有没有用.......感觉 实时计算 比 存储临时价格 更合理, 前者是快慢问题,后者是逻辑问题。考虑 价格顺序对使用者的重要性 和 响应快慢对使用者的重要性 ?🧐🧐 我看到这段文字的一些零散想法....... hhh

折扣是否经常变动.......

系统对内对外?一个供应商超过 50 万,但一个商品应该没有 50 万个供应商吧。如果一次展示的搜索结果不多,也不怕数据被人抓取的话,直接把数据全扔给客户端,让客户端自己算去。

存折后价

变更少。可能 1 天 或 几天更新一次。供应商数量不算多,几百家的样子。

可能几百家供应商。一个商品可能只有 3 - 5 个供应商卖,但相似的商品有蛮多供应商卖。

大致是这规则,但每家原价不同折扣率可能也不同,所以一家供应商的按原价和重量比较也是大致相同的排序结果,但 不同供应商一起来比较就要计算后才知道。 现在的程序是查询时让 SQL 计算排序,但感觉比较慢。

从业务入手,看能不能提前制定折扣计划,比如 1 号之前配置 1-3 号的折扣,这样有充足的时间去计算折后价。如果非要实时调整,那除了变动后计算,通过分组并发建结果表等常规方式计算没啥办法,你肯定不能每次查询再去计算的

先算好存在另一张这算表中,在监听供应商改折扣在重新计算相关的商品,有一定的延迟,但也不会很大。如果实时算性能挺不住

可以考虑做结果表保存折后价,用 canal 监听折扣表,有变动就更新一下结果表

我们公司很简单,把这种和价格相关的数据全部放到 redis 里,根本不走 mysql

我们业务比你们更加复杂,我们的价格在不同人,不同时间,不同供应商,不同细项,价格全部不一样。当多个日期或者类型选择时需要以平局价格过滤排序,我们目前数据量 100 亿+查询接口 QPS 100 左右,我们用的 StarRocks 。这里同样好奇,这种涉及数据规模大,计算复杂的查询逻辑其他公司是怎么做的

用 SQL 表述查询逻辑大概是这样的:Select product_id, avg(price) as avg_pricefrom sku_tablewhere time > xxx and time < xxx and xxxxxxgroup by product_idhaving avg_price > xxx and avg_price < xxxorder by avg_price

留个标记,求教大佬

如果事先计算,把不同情况下的结果存到数据库里面去。需要考虑的就是存储的数据量的量级和读取效率问题。同事这种结构的数据,不管是 redis ,mongo ,还是 es 都有办法解决。但是如果是实时计算的话,对计算的要求会比较高,扩展起来复杂。

是商品总数量 1000W 还是 skuid1000 万?感觉一个供应商最多也就几百件商品吧,放到 redis 里排序就行

TB 你按价格排序, 它也不是按价格排序的所以,凑活弄弄就行了 :P

网页客户端,还要支持小程序和手机等,没法让客户端处理数据

标记

实际上这个就是搜索引擎的需求,你在做排名相关工作。我的建议是,后台有服务不断根据需求更新索引。然后用户实际搜索的时候,就可以通过索引快速查询到商品