2017-07-24 70 views
0

假設某些數據庫(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] 

它的工作原理,但也許是一個更有效的解決方案存在。請您指出正確的方向。

+0

也許更適合於[代碼評審]中心( https://codereview.stackexchange.com/)。 – jwvh

+0

另一點是,沒有什麼能阻止你詢問所有異步查詢(它可能會比順序詢問它們要快),但你仍然會受到db性能的瓶頸 – Nils

回答

0

難道你不能簡單地在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

另外,最好使用降()/取()直接在油滑,以及:

val streamT1 = Source.fromPublisher(db.stream(
     (Q1 unionAll Q2 unionAll Qn) 
     .sortBy(time) 
     .drop(pageSize*pageNumber).take(pageSize)))