Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Postgresql高效查询最新记录_Sql_Postgresql_Subquery_Distinct - Fatal编程技术网

使用Postgresql高效查询最新记录

使用Postgresql高效查询最新记录,sql,postgresql,subquery,distinct,Sql,Postgresql,Subquery,Distinct,我需要做一个大的查询,但我只想要最新的记录 对于一个条目,我可能会这样做 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.i

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

对于一个条目,我可能会这样做

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);

这可能更有效。差异:表b的查询只执行一次,您的相关子查询针对每一行执行:

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 

如果每个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可能是FKs到另一个表中,请使用此表。

关于方法-创建一个包含表a上最新更新/插入时间的小型衍生表-将此表称为a_latest。表a\u 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 );
诀窍是保持最新的。在插入和更新时使用触发器执行此操作。用plppgsql编写的触发器相当容易编写。如果你愿意,我很乐意举个例子


这里的要点是,最新更新时间的计算是在更新过程中进行的。这会转移查询的更多负载。

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

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

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”表本身中。

您对此有何看法

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

我过去经常使用它

认为这看起来很有希望,但连接效率很低。为什么你认为连接效率很低,特别是考虑到它只连接一行?在测试了这两种方法后,max(date)比DISTINCT on快了大约3倍。这真是一个很好的解决方案!谢谢!我的查询时间从470毫秒缩短到95毫秒。我已经使用max(id)作为最后一行标识符。因此,它可以比日期时间比较更有效。在我的例子中,
用户
表包含系统的所有用户,
邀请
表包含为成为用户而发送的所有邀请。每个电子邮件地址可以发送多个邀请,每个邀请都有一个
有效期
日期、一个
邀请
接受标志和一个
创建日期
。我们只关心最近的邀请。如果您接受在所有列上使用聚合函数,性能会使这成为最佳答案。那么,my
SELECT DISTINCT
query是否有任何帮助?它应该比相关的子选择更快,但我不确定要快多少。如果您正在寻找更有效的解决方案,请使用此选项,试试下面Manji的答案。它的基准测试速度比使用这里介绍的DISTINCT ON解决方案快3倍左右。这家伙全力以赴:
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