簡體   English   中英

如何將對多個表行的查詢轉換為使用單個數組?

[英]How to convert a query on multiple table rows into using a single array?

我以前有這張表:

CREATE TABLE traces_v0
 ( canvas_id UUID NOT NULL
 , tlid BIGINT NOT NULL
 , trace_id UUID NOT NULL
 , timestamp TIMESTAMP WITH TIME ZONE NOT NULL
 , PRIMARY KEY (canvas_id, tlid, trace_id)
 );

我正在嘗試將其更改為這張表:

CREATE TABLE traces_v0
 ( canvas_id UUID NOT NULL
 , root_tlid BIGINT NOT NULL
 , trace_id UUID NOT NULL
 , callgraph_tlids BIGINT[] NOT NULL
 , timestamp TIMESTAMP WITH TIME ZONE NOT NULL
 , PRIMARY KEY (canvas_id, root_tlid, trace_id)
 );

也就是說,以前每個(tlid, trace_id)有一行,現在只有一行帶有trace_idcallgraph_tlids數組。

我有一個在舊表上運行良好的查詢:

SELECT tlid, trace_id
  FROM (
    SELECT
      tlid, trace_id,
      ROW_NUMBER() OVER (PARTITION BY tlid ORDER BY timestamp DESC) as row_num
    FROM traces_v0
    WHERE tlid = ANY(@tlids::bigint[])
      AND canvas_id = @canvasID
  ) t
  WHERE row_num <= 10

這會為每個按時間戳排序的tlids (一個 bigint 數組)獲取最后 10 個(tlid, trace_id) trace_id)。 這正是我所需要的,而且非常有效。

(僅供參考:“at”( @tlids )語法只是編寫$1的一種奇特方式,由我的 postgres 驅動程序支持)

我正在努力將其移植到新的表格布局中。 我想出了以下可行的方法,但它不限於按時間戳排序的每個tlid 10 個:

SELECT callgraph_tlids, trace_id
FROM traces_v0
WHERE @tlids && callgraph_tlids  -- '&&' is the array overlap operator
  AND canvas_id = @canvasID
ORDER BY timestamp DESC"

我如何執行此查詢,其中我將結果限制為每個tlid 10 行,按時間戳排序?

如果重要的話,我正在使用 Postgres 9.6。

我如何執行此查詢,其中我將結果限制為每個 tlid 10 行,按時間戳排序?

如果在新設計中聚合到同一數組中的舊設計中所有行的時間戳始終相同,那么新設計的這個查詢在邏輯上是等價的:

SELECT trace_id, tlid
FROM  (
   SELECT t.trace_id, c.tlid
        , row_number() OVER (PARTITION BY c.tlid ORDER BY t.timestamp DESC) AS rn
   FROM   traces_v0 t
   JOIN   LATERAL unnest(t.callgraph_tlids) c(tlid) ON c.tlid = ANY(@tlids)
   WHERE  t.canvas_id = @canvasid
   AND    t.callgraph_tlids && @tlids
   ) sub
WHERE  rn <= 10;

但這意味着ORDER BY timestamp DESC一直是非確定性排序順序,您的新查詢與舊查詢一樣不可靠。 前 10 名可能會從一次查詢調用更改為下一次調用。 如果您想要確定性結果,請將更多表達式作為決勝局添加到ORDER BY列表中,直到排序順序明確無誤 - 可能在任何情況下。

在連接條件ON c.tlid = ANY(@tlids)之上的WHERE條件t.callgraph_tlids && @tlids在邏輯上是多余的,但通常有助於使您的查詢更快,尤其是callgraph_tlids上使用 GIN 索引時 看:

關於LATERAL連接:

甚至可以在您過時的、不受支持的 Postgres 9.6 中使用。 但無論如何都要升級到當前版本

如果聚合行的時間戳不同,那么答案是:你不能。

新設計刪除了必需的信息。 舊設計對每個tlid都有一個單獨的時間戳,而新設計對整個數組 ( callgraph_tlids ) 只有一個時間戳。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM