如何在变化的表格中找不到不同的行

时间:2017-03-14 21:18:14

标签: sql postgresql limit offset

我有一个数百万行不断变化的表(新行被插入,更新,有些被删除)。我想每分钟查询100个新行(我之前没有查询过),但这些行不能是我以前查询过的行。该表有大约24列和一个主键。

乐意回答任何问题或提供澄清。

2 个答案:

答案 0 :(得分:2)

一个简单的解决方案是让一个单独的表只有一行来存储你提取的最后一个ID。

让我们说这是数百万行的表格":

-- That's your table with million of rows
CREATE TABLE test_table (
    id serial unique,
    col1 text,
    col2 timestamp
);

-- Data sample
INSERT INTO test_table (col1, col2)
SELECT 'test', generate_series
FROM generate_series(now() - interval '1 year', now(), '1 day');

您可以创建以下表来存储ID:

-- Table to keep last id
CREATE TABLE last_query (
  last_quey_id int references test_table (id)
);
-- Initial row
INSERT INTO last_query (last_quey_id) VALUES (1);

然后使用以下查询,您将始终获取从原始表中永远不会获取的100行并在last_query中维护指针:

WITH last_id as (
    SELECT last_quey_id FROM last_query
), new_rows as (
    SELECT *
    FROM test_table
    WHERE id > (SELECT last_quey_id FROM last_id)
    ORDER BY id
    LIMIT 100
), update_last_id as (
    UPDATE last_query SET last_quey_id = (SELECT MAX(id) FROM new_rows)
)
SELECT * FROM new_rows;

将按新ID(最早的行首先)的顺序提取行。

答案 1 :(得分:1)

您基本上需要一个唯一的顺序值,该值分配给此表中的每个记录。这允许您搜索下一个X记录,其中该字段的值大于您从上一页获得的最后一个。

最简单的方法是将标识列作为您的PK,并从头开始并在查询中包含“where id> @last_id”过滤器。无论底层更新如何,这都是一种非常直接的数据分页方式。但是,如果你已经拥有数百万行并且不断创建和更新,那么一个普通的整数身份最终将会耗尽数字(一个bigint身份列不太可能在你的曾孙子的一生中耗尽数字,但不会所有数据库都支持除32位标识之外的所有内容。)

您可以使用“CreatedDate”日期时间列执行相同操作,但由于这些日期不是100%保证唯一,因此根据此日期的设置方式,您可能拥有多个具有相同创建时间戳的行,如果这些记录越过“页面边界”,您将错过任何超出当前页面结尾的记录。

保证某些SQL系统的GUID生成器不仅是唯一的,而且是顺序的。您将不得不调查PostgreSQL的GUID是否以这种方式工作;如果他们是真正的V4 GUID,他们将完全随机,除了版本标识符,你是SOL。如果您确实可以访问顺序GUID,则可以像使用整数标识列一样进行过滤,只能使用更多可能的键值。