以前单位比较依赖 DBA,高级点的数据库优化可以交给 dba 出方案,基本不用开发考虑,现在换了工作接手维护一个项目,不是个技术型公司,需要开发“全能”型。
涉及 3 个表,其中有个表同时存在级联逻辑。页面查询要求同时展示所有子级信息。
比如顶级用户 1,列表页需要同时展示,2,3,4,5 级。
二级用户 2,列表需要查询 3,4,5 级,,,,
我看了下,上一个开发留的方案是,数据库视图,除了基础 2 张表+级联表做了基础数据之外,重复关联 5 次级联逻辑的表,对外表现成了 8 张表做内连接,查询顶级用户 1,耗时 7 秒
我的方案是去掉后 5 张表的关联,变为 2s,然后前台二次查询单独实现级联数据,但是老员工对于这个改造的工作量不太满意(不知道是不是懒)。
各位走过路过支个招,还有啥别的方案改动少可以满足提速需求?
1
Mazexal 2018-05-14 09:19:30 +08:00
创建了索引没....一个查询 7 秒多怎么想都觉得太可怕了吧....
|
2
opengps OP @Mazexal 我给级联字段加了索引之后 7 秒,慢主要是因为数据多,还重复关联导致的,页面没有分页,因为业务上最大顶级用户也不会有太多行结果
|
3
ykrl089 2018-05-14 09:23:17 +08:00
你这个感觉有点像是传销啊……
|
4
h1367500190 2018-05-14 09:23:50 +08:00 1
了解下嵌套集合模型(Nested set model)?
|
6
justfindu 2018-05-14 09:27:03 +08:00
可以改表不, 改成用 depth, lft, rgt 来标记级联. 一次性修改全表,增加这些字段. 之后查询就是一个语句
|
7
RubyJack 2018-05-14 09:31:37 +08:00 1
冗余第一级,这样查询的时候,只要通过第一级就可以查出全部 5 级的数据,之后业务代码里拼装成级联的即可
|
8
opengps OP @justfindu depth 这个办法不错,至少大幅减小了关联时候临时数据集大小,我试试。lft, rgt 我怎么用合适?类似 depth 他原来有个当前第几级的标识列,这个需求只有父级差子级,我是不是用不到?
|
10
Troevil 2018-05-14 09:34:28 +08:00
一般有固定级联的都是空间换时间, 冗余数据
|
13
justfindu 2018-05-14 09:42:18 +08:00 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 ,查出所有的子级 |
14
l00t 2018-05-14 09:52:44 +08:00 1
如果是 Oracle 数据库的话,类似需求我一般使用层级查询,也就是 start with.... connect by.... 那套。
使用这个方案需要在表内加一个字段注明某条记录的上一级是谁。 但是具体到你的情况,还得看 数据量, 表结构,以及现有查询方案的表现来决定优化方案。你啥都没贴,那就没啥可帮的了…… |
15
corningsun 2018-05-14 18:08:59 +08:00 1
可以试下减少数据库查询次数,优点是不需要修改现在的表结构。
查第一层 得到 所有的 level_1_ids 再根据 level_1_ids 去查第二层 level_2_ids 基本只需要查询很少的次数,然后基本都是内存操作了,只要内存够,性能 应该没啥问题。 Java 的 stream 操作,做这些事情还是挺顺手的。。 当然由于非常依赖内存和 cpu,数据量到底有多大,还需要考虑实际情况。 |
16
fuxkcsdn 2018-05-15 00:17:20 +08:00 via iPhone
|