sql-使用Postgresql进行高效的最新记录查询

我需要做一个大查询,但是我只想要最新记录。

对于单个条目,我可能会做类似的事情

SELECT * FROM table WHERE id = ? ORDER BY date DESC LIMIT 1;

但是我需要提取大量(数千个条目)记录的最新记录,而仅获取最新记录。

这就是我所拥有的。 这不是很有效。 我想知道是否有更好的方法。

SELECT * FROM table a WHERE ID IN $LIST AND date = (SELECT max(date) FROM table b WHERE b.id = a.id);
Sheldon Ross asked 2020-06-27T16:01:18Z
5个解决方案
47 votes

如果您不想更改数据模型,则可以使用a.id从表“ b”中获取“ a”中每个条目的最新记录:

SELECT DISTINCT ON (a.id) *
FROM a
INNER JOIN b ON a.id=b.id
ORDER BY a.id, b.date DESC

如果您想避免查询中的“排序”,则添加这样的索引可能会有所帮助,但是我不确定:

CREATE INDEX b_id_date ON b (id, date DESC)

SELECT DISTINCT ON (b.id) *
FROM a
INNER JOIN b ON a.id=b.id
ORDER BY b.id, b.date DESC

或者,如果您想以某种方式对表“ a”中的记录进行排序:

SELECT DISTINCT ON (sort_column, a.id) *
FROM a
INNER JOIN b ON a.id=b.id
ORDER BY sort_column, a.id, b.date DESC

替代方法

但是,以上所有查询仍然需要从表“ b”中读取所有引用的行,因此,如果您有大量数据,它可能仍然太慢。

您可以创建一个新表,该表仅保存每个a.id的最新“ b”记录-甚至可以将这些列移到“ a”表本身中。

intgr answered 2020-06-27T16:01:57Z
35 votes

这可能会更有效率。 区别:表b的查询仅执行1次,相关的子查询每行执行一次:

SELECT * 
FROM table a 
JOIN (SELECT ID, max(date) maxDate
        FROM table
      GROUP BY ID) b
ON a.ID = b.ID AND a.date = b.maxDate
WHERE ID IN $LIST 
manji answered 2020-06-27T16:02:20Z
4 votes

On方法-在表a上创建一个包含最新更新/插入时间的小型派生表-将此表称为a_latest。 表a_latest将需要足够的粒度以满足您的特定查询要求。 在您的情况下,使用就足够了

CREATE TABLE 
a_latest 
( id INTEGER NOT NULL, 
  date TSTAMP NOT NULL, 
  PRIMARY KEY (id, max_time) );

然后使用类似于najmeddine建议的查询:

SELECT a.* 
FROM TABLE a, TABLE a_latest 
USING ( id, date );

然后,诀窍是使a_latest保持最新。 使用插入和更新触发器来执行此操作。 用plppgsql编写的触发器很容易编写。 如果您愿意,我很乐意提供一个例子。

这里的要点是,在更新本身期间会考虑最新更新时间的计算。 这会将更多的负载转移到查询之外。

youngthing answered 2020-06-27T16:02:53Z
3 votes

你怎么看待这件事?

select * from (
   SELECT a.*, row_number() over (partition by a.id order by date desc) r 
   FROM table a where ID IN $LIST 
)
WHERE r=1

我过去经常用

unknown answered 2020-06-27T16:03:19Z
1 votes

如果每个id有很多行,则绝对需要一个相关的子查询。它将对每个id进行1次索引查找,但这比对整个表进行排序要快。

就像是 :

SELECT a.id,
(SELECT max(t.date) FROM table t WHERE t.id = a.id) AS lastdate
FROM table2;

您将使用的“ table2”不是您在上面的查询中提到的表,因为要获得良好的性能,这里需要一个不同的ID列表。 由于您的ID可能是进入另一个表的FK,因此请使用此表。

peufeu answered 2020-06-27T16:03:48Z
translate from https://stackoverflow.com:/questions/1684244/efficient-latest-record-query-with-postgresql