我以前有这个表:
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_id
和一个callgraph_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)
,这正是我所需要的,而且非常有效。
(fyi:“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,如果有问题的话。
1条答案
按热度按时间2o7dmzc51#
如果我将结果限制为每个tlid 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中工作。但是无论如何upgrade to a current version。
新设计删除了必需的信息。旧设计对每个
tlid
都有单独的时间戳,而新设计对整个阵列(callgraph_tlids
)只有一个时间戳。