全表价格排序的性能

2024-01-25 01:03:17 +08:00
 dyv9
一些外行的产品设计师抄来别人的界面,把所有用户角色的功能尽量共用一个版面,比如管理员和买家卖家共用产品维护和购买检索的页面,还默认进入页面就不带任何条件就按价格排序分页,价格由 ( 原价 + 厂家折扣 + 卖家折扣 + 买家折扣 ) X 汇率。现在是 查询时计算价格然后排序,因为允许不带条件查询,一全表排序了,300 万条要 10 秒以上才返回,性能无法接受。

我考虑先卖家相关的价格 (原价 + 厂家折扣 + 卖家折扣)先计算在单独栏位,想用价格列上建覆盖索引,但随后 + 买家折扣又导致价格列上的索引用不了。 感觉没用,仅仅是查询时计算少了一个 加减运算,索引依然没用。

跟产品建议了把功能拆解,不要默认无条件搜索,尽量要让带条件搜索,他理解不了,执意要这样搞,各位不知咋办呢,有啥建议呀?

难道只有跑路一个选项吗?😂
2473 次点击
所在节点    MySQL
14 条回复
opengps
2024-01-25 03:17:44 +08:00
sql 语句里带上 强制索引
Rocketer
2024-01-25 07:28:41 +08:00
这坑明显在实时计算上,你只需定时计算即可提前排好索引了。计算间隔看需求,反正京东淘宝都挺长的,发布商品后很久才能进入列表。
lsk569937453
2024-01-25 08:47:57 +08:00
你们的产品挺 2 的。
这个默认进入页面查询的功能,应该设计成进入页面查询则使用默认条件查询而不是没有条件直接查全表。
kuber
2024-01-25 09:30:51 +08:00
改产品设计吧。我对问题的理解是买家/卖家因为各自相关产品量小,所以没有性能问题,但是管理员因为要管理所有产品( 300 万+),因此产生性能问题,不知道理解对不对。
找到管理员聊一下,了解一下他们在产品维护页面最常用的操作, 以此作为产品设计优化的出发点。
我一直认为作为技术人员要发展的话,需要不断提高沟通和说服的能力,要不然以后发展空间有限。好的技术人员应该是一个好的技术销售,向团队,上级和客户销售自己的想法。
kuber
2024-01-25 09:32:19 +08:00
反正你已经把跑路当作一个选项了,不如尝试一下说服你们的产品,就当作公司付钱给你练习沟通方法的技巧。:-P
rekulas
2024-01-25 09:56:12 +08:00
那这种情况使用 mysql 来排序其实并不合适了,毕竟涉及到硬盘 io 速度上不去,你可以考虑自己实现一个基于内存的常驻微服务,商品有更新就同步到内存,基本可以秒出
rekulas
2024-01-25 09:59:35 +08:00
对了你还可以试试 mysql 的内存表,如果能满足需求改动更小
buliugu
2024-01-25 10:17:07 +08:00
直接上 es 得了,计算字段啥的全部塞进去,然后做好更新策略就行,300w+ es 可以做到秒回
burymme11
2024-01-25 10:24:22 +08:00
MySQL 里面放原数据,在 Redis 里面用价格索引+dbId 建个 sortedSet ,定时刷新这个 set 。在分页的时候先去 Redis 里拿 id ,再去 MySQL 里面查。这样试试呢?
linauror
2024-01-25 11:07:03 +08:00
(原价 + 厂家折扣 + 卖家折扣)先计算在单独栏位,这个思路是对的,然后买家折扣和汇率可以当成常量,因为针对当前这个查询的人,买家折扣应该是固定的。可以直接根据上面的单独字段排序后返回给程序,由程序再做后面的具体价格计算,这样查询应该会快很多
dyv9
2024-01-25 12:50:45 +08:00
@linauror 这个汇率还不是常量,而是每个供应商和卖家组合才唯一的汇率。一个供应商可以给多个卖家不同汇率。原来我想把它们折算成供应商折扣不就行了,产品和老板说不是一回事,事情比想象的要复杂。
qiyilai
2024-01-25 14:22:46 +08:00
换数据库,doris
jones2000
2024-01-25 14:41:24 +08:00
数据下本地,开几个 worker 排下序, 也就 300W 数据, 排次序花不了多长时间。
MoYi123
2024-01-25 15:20:48 +08:00
n = 3000000
id = [i for i in range(n)]
原价 = [random.random() * 99999999 for _ in range(n)]
厂家折扣 = [random.random() * 1000 for _ in range(n)]
卖家折扣 = [random.random() * 1000 for _ in range(n)]
买家折扣 = [random.random() * 1000 for _ in range(n)]
汇率 = [random.random() * 10 for _ in range(n)]

table = list(zip(id, 原价, 厂家折扣, 卖家折扣, 买家折扣, 汇率))


def sort_by(row):
id, 原价, 厂家折扣, 卖家折扣, 买家折扣, 汇率 = row
return 原价 - 厂家折扣 - 卖家折扣 - 买家折扣 * 汇率


import time

start = time.time()
table.sort(key=sort_by)

print(time.time() - start) # 1.0334241390228271


300w 行用 python 全部排序也才 1 秒, 数据库里 c/c++的排序怎么可能要 10 秒呢?
况且 limit n 的情况下只需要 O(n)的排序算法. python 里的还是 O(nlogn)的.

你该不会是把数据全拉到本地再计算的吧.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/1011343

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX