V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
dyv9
V2EX  ›  MySQL

全表价格排序的性能

  •  
  •   dyv9 · 298 天前 via Android · 2384 次点击
    这是一个创建于 298 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一些外行的产品设计师抄来别人的界面,把所有用户角色的功能尽量共用一个版面,比如管理员和买家卖家共用产品维护和购买检索的页面,还默认进入页面就不带任何条件就按价格排序分页,价格由 ( 原价 + 厂家折扣 + 卖家折扣 + 买家折扣 ) X 汇率。现在是 查询时计算价格然后排序,因为允许不带条件查询,一全表排序了,300 万条要 10 秒以上才返回,性能无法接受。

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

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

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

    你该不会是把数据全拉到本地再计算的吧.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1804 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:42 · PVG 00:42 · LAX 08:42 · JFK 11:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.