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

2018-05-14 09:11:33 +08:00
 opengps

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

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

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

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

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

4347 次点击
所在节点    MySQL
16 条回复
Mazexal
2018-05-14 09:19:30 +08:00
创建了索引没....一个查询 7 秒多怎么想都觉得太可怕了吧....
opengps
2018-05-14 09:21:07 +08:00
@Mazexal 我给级联字段加了索引之后 7 秒,慢主要是因为数据多,还重复关联导致的,页面没有分页,因为业务上最大顶级用户也不会有太多行结果
ykrl089
2018-05-14 09:23:17 +08:00
你这个感觉有点像是传销啊……
h1367500190
2018-05-14 09:23:50 +08:00
了解下嵌套集合模型(Nested set model)?
opengps
2018-05-14 09:24:23 +08:00
@ykrl089 确实像,每个顶级用户拉不了多少下级。。。但是顶级用户数量会比较快的增长
justfindu
2018-05-14 09:27:03 +08:00
可以改表不, 改成用 depth, lft, rgt 来标记级联. 一次性修改全表,增加这些字段. 之后查询就是一个语句
RubyJack
2018-05-14 09:31:37 +08:00
冗余第一级,这样查询的时候,只要通过第一级就可以查出全部 5 级的数据,之后业务代码里拼装成级联的即可
opengps
2018-05-14 09:32:18 +08:00
@justfindu depth 这个办法不错,至少大幅减小了关联时候临时数据集大小,我试试。lft, rgt 我怎么用合适?类似 depth 他原来有个当前第几级的标识列,这个需求只有父级差子级,我是不是用不到?
opengps
2018-05-14 09:33:56 +08:00
@RubyJack 不是太明白,可否稍微详细指点下
Troevil
2018-05-14 09:34:28 +08:00
一般有固定级联的都是空间换时间, 冗余数据
justfindu
2018-05-14 09:34:58 +08:00
@opengps 搜一下 "无限级联" , 方案就是那个.
justfindu
2018-05-14 09:36:40 +08:00
@justfindu "无限级分类"
justfindu
2018-05-14 09:42:18 +08:00
@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
2018-05-14 09:52:44 +08:00
如果是 Oracle 数据库的话,类似需求我一般使用层级查询,也就是 start with.... connect by.... 那套。
使用这个方案需要在表内加一个字段注明某条记录的上一级是谁。

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

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


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

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

http://www.cnblogs.com/alex2moro/archive/2013/01/03/2842637.html

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

https://www.v2ex.com/t/454590

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

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

© 2021 V2EX