假设某些数据库(PostgreSQL)中有N
个表。每个表Ti
都包含字段(time, label)
,其中time
是某个数字(例如,长timestamp
)。 label
是一些文字。
有N
个条件。每个条件Ci
都应用于特定表Ti
。每个条件都可能很复杂(使用自己的子查询,也可以加入)。
我需要从条件中收集所有表T
中的记录,并获取一个排序结果页面。此任务由SQL
和UNION ALL
解决。以下伪说明了获取某些页面:
(SELECT time, label FROM T1 WHERE C1
UNION ALL
SELECT time, label FROM T2 WHERE C2
UNION ALL
...
SELECT time, label FROM Tn WHERE Cn)
ORDER BY time LIMIT = x OFFSET = y
DISTINCT
如果条件C
复杂且表包含大量记录,则上述查询非常庞大且缓慢。
我想将这个复杂的查询拆分为子查询,其中每个子查询Qi
都应用于相应的表Ti
。在这种情况下,每个子查询执行得更快,但问题与联合结果有关,对分页进行排序会引发。
为此,我将使用akka-streams
和slick-streaming
。以下伪代码说明了为两个表提取一些页面:
val streamT1 = Source.fromPublisher(db.stream(Q1.sortBy(time)))
val streamT2 = Source.fromPublisher(db.stream(Q2.sortBy(time)))
val pageContent = streamT1.mergeSorted(streamT2)
.grouped(pageSize).drop(pageNumber)
.runWith(Sink.headOption)
以下示例说明了两个表的分页:
val srcT1 = Source(
(0, "A_a"),
(1, "A_b"),
(2, "A_c"),
(5, "A_d"),
(7, "A_e"),
(8, "A_f"),
(9, "A_g"),
(10, "A_h"),
(11, "A_i"),
(15, "A_j"),
(16, "A_k"),
(17, "A_l"),
(20, "A_m"),
...
)
val srcT2 = Source(
(3, "B_d"),
(12, "B_e"),
(18, "B_f"),
...
)
以上馆藏的时间表图如下:
0 1 2 5 7 8 9 10 11 15 16 17 20
| | | | | | | | | | | | |
A_a---A_b---A_c---------------A_d---------A_e---A_f---A_g---A_h---A_i---------------------A_j---A_k---A_l---------------A_m--->
3 12 18
| | |
------------------B_d---------------------------------------------------B_e---------------------------------B_f--------------->
包含page-size=4
并按time
排序的网页:
[A_a,A_b,A_c,B_d] [A_d,A_e,A_f,A_g] [A_h,A_i,B_e,A_j] [A_k,A_l,B_f,A_m]
它有效,但也许存在更有效的解决方案。如果你指出正确的方向,将不胜感激。
答案 0 :(得分:0)
您是否可以在Slick中使用unionAll
操作?
val streamT1 = Source.fromPublisher(db.stream(
(Q1 unionAll Q2 unionAll Qn).sortBy(time) ))
Cf:http://slick.lightbend.com/doc/3.0.0/queries.html#unions
另外,最好直接在Slick中使用drop()/ take():
val streamT1 = Source.fromPublisher(db.stream(
(Q1 unionAll Q2 unionAll Qn)
.sortBy(time)
.drop(pageSize*pageNumber).take(pageSize) ))