› 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
opengps
0.01D
V2EX  ›  MySQL

请教个数据库问题, 5 层固定级联,有啥最好方案查询?

  •  
  •   opengps ·
    null · May 14, 2018 · 5522 views
    This topic created in 3061 days ago, the information mentioned may be changed or developed.

        以前单位比较依赖 DBA,高级点的数据库优化可以交给 dba 出方案,基本不用开发考虑,现在换了工作接手维护一个项目,不是个技术型公司,需要开发“全能”型。

        涉及 3 个表,其中有个表同时存在级联逻辑。页面查询要求同时展示所有子级信息。
    比如顶级用户 1,列表页需要同时展示,2,3,4,5 级。 二级用户 2,列表需要查询 3,4,5 级,,,,

        我看了下,上一个开发留的方案是,数据库视图,除了基础 2 张表+级联表做了基础数据之外,重复关联 5 次级联逻辑的表,对外表现成了 8 张表做内连接,查询顶级用户 1,耗时 7 秒

        我的方案是去掉后 5 张表的关联,变为 2s,然后前台二次查询单独实现级联数据,但是老员工对于这个改造的工作量不太满意(不知道是不是懒)。

        各位走过路过支个招,还有啥别的方案改动少可以满足提速需求?

    16 replies  •  2018-05-15 00:17:20 +08:00
    Mazexal
        1
    Mazexal  
       May 14, 2018
    创建了索引没....一个查询 7 秒多怎么想都觉得太可怕了吧....
    opengps
        2
    opengps  
    OP
       May 14, 2018
    @Mazexal 我给级联字段加了索引之后 7 秒,慢主要是因为数据多,还重复关联导致的,页面没有分页,因为业务上最大顶级用户也不会有太多行结果
    ykrl089
        3
    ykrl089  
       May 14, 2018
    你这个感觉有点像是传销啊……
    h1367500190
        4
    h1367500190  
       May 14, 2018   ❤️ 1
    了解下嵌套集合模型(Nested set model)?
    opengps
        5
    opengps  
    OP
       May 14, 2018
    @ykrl089 确实像,每个顶级用户拉不了多少下级。。。但是顶级用户数量会比较快的增长
    justfindu
        6
    justfindu  
       May 14, 2018
    可以改表不, 改成用 depth, lft, rgt 来标记级联. 一次性修改全表,增加这些字段. 之后查询就是一个语句
    RubyJack
        7
    RubyJack  
       May 14, 2018   ❤️ 1
    冗余第一级,这样查询的时候,只要通过第一级就可以查出全部 5 级的数据,之后业务代码里拼装成级联的即可
    opengps
        8
    opengps  
    OP
       May 14, 2018
    @justfindu depth 这个办法不错,至少大幅减小了关联时候临时数据集大小,我试试。lft, rgt 我怎么用合适?类似 depth 他原来有个当前第几级的标识列,这个需求只有父级差子级,我是不是用不到?
    opengps
        9
    opengps  
    OP
       May 14, 2018
    @RubyJack 不是太明白,可否稍微详细指点下
    Troevil
        10
    Troevil  
       May 14, 2018
    一般有固定级联的都是空间换时间, 冗余数据
    justfindu
        11
    justfindu  
       May 14, 2018   ❤️ 1
    @opengps 搜一下 "无限级联" , 方案就是那个.
    justfindu
        12
    justfindu  
       May 14, 2018   ❤️ 1
    @justfindu "无限级分类"
    justfindu
        13
    justfindu  
       May 14, 2018   ❤️ 2
    @opengps 其实就是一个树型的结构. 父级 的左标记 lft 为起点, 然后所有子级都有各自的左节点和右节点基数. 最后回到到父级的右标记 rgt 计数.
    类似 A 有 B C D, B 有 E F,
    那么
    A.lft = 1 ,
    B.lft = 2 ,
    E.lft=3, E.rgt =4, F.lft = 5, F.rgt = 6, B.rgt = 7, C.lft=8 ,C.rgt = 9, D.lft=10, D.rgt=11, A.rgt=12,

    然后 A.depth = 0 , B C D depth = 1, E F depth = 2,

    这样可以通过 查询 lft > A.lft 并且 rgt < A.rgt ,查出所有的子级
    l00t
        14
    l00t  
       May 14, 2018   ❤️ 1
    如果是 Oracle 数据库的话,类似需求我一般使用层级查询,也就是 start with.... connect by.... 那套。
    使用这个方案需要在表内加一个字段注明某条记录的上一级是谁。

    但是具体到你的情况,还得看 数据量, 表结构,以及现有查询方案的表现来决定优化方案。你啥都没贴,那就没啥可帮的了……
    corningsun
        15
    corningsun  
       May 14, 2018   ❤️ 1
    可以试下减少数据库查询次数,优点是不需要修改现在的表结构。

    查第一层 得到 所有的 level_1_ids
    再根据 level_1_ids 去查第二层 level_2_ids
    基本只需要查询很少的次数,然后基本都是内存操作了,只要内存够,性能 应该没啥问题。


    Java 的 stream 操作,做这些事情还是挺顺手的。。

    当然由于非常依赖内存和 cpu,数据量到底有多大,还需要考虑实际情况。
    fuxkcsdn
        16
    fuxkcsdn  
       May 15, 2018 via iPhone
    可以参考下这方案(和 13 楼说的应该是同一方案)

    http://www.cnblogs.com/alex2moro/archive/2013/01/03/2842637.html
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   3185 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 41ms · UTC 04:38 · PVG 12:38 · LAX 21:38 · JFK 00:38
    ♥ Do have faith in what you're doing.