优化复杂查询(使用分页)



假设某个数据库(PostgreSQL(中有N表。每个表Ti都包含字段(time, label),其中time是某个数字(例如长timestamp(。label是一些文本。

N条件。每个条件Ci都应用于特定的表Ti。每个条件都可能很复杂(使用自己的子查询,也使用连接(。

我需要从所有T有条件的表中收集记录,并获得一页排序结果。此任务由SQLUNION 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-streamsslick-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]

它有效,但也许存在更有效的解决方案。如果您指出正确的方向,将不胜感激。

你不能简单地使用 Slick 中的unionAll操作吗?

val streamT1 = Source.fromPublisher(db.stream(
(Q1 unionAll Q2 unionAll Qn).sortBy(time) ))

参考: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) ))

相关内容

  • 没有找到相关文章

最新更新