3

我在一个表中有超过 1000 万条记录。

SELECT * FROM tbl ORDER BY datecol DESC
LIMIT 10
OFFSET 999990

explain.depesz.comEXPLAIN ANALYZE上的输出。 执行上述查询大约需要 10 秒。我怎样才能让它更快?

更新

通过使用子查询,执行时间减少了一半:

SELECT * FROM tbl where id in 
(SELECT id FROM tbl ORDER BY datecol DESC LIMIT 10 OFFSET 999990)

explain.depesz.comEXPLAIN ANALYZE上的输出。

4

2 回答 2

2

您需要在中使用的列上创建索引ORDER BY。理想情况下以相同的排序顺序,但 PostgreSQL 可以以几乎相同的速度向后扫描索引。

CREATE INDEX tbl_datecol_idx ON tbl (datecol DESC);

有关索引CREATE INDEX当前手册的更多信息。
测试EXPLAIN ANALYZE以获取除查询计划之外的实际时间。

当然,所有关于性能优化的常用建议也适用。

于 2013-03-16T01:53:44.580 回答
0

我试图用一个非常大的表(>100m 记录)做一些与我自己类似的事情,并发现使用 Offset / Limit 会降低性能。前 10m 条记录的偏移量(限制为 1)大约需要 1.5 分钟才能检索,并且它呈指数增长。通过记录 50m,我每次选择最多 3 分钟 - 即使使用子查询。

我在这里看到了一篇文章,其中详细介绍了有用的替代方案

我稍微修改了一下以适应我的需要,并提出了一种可以很快获得结果的方法。

CREATE TEMPORARY TABLE 
just_index AS SELECT ROW_NUMBER() 
OVER (ORDER BY [VALUE-You-need]), [VALUE-You-need] 
FROM [your-table-name];

这是一次性的——大约花了 4 分钟,但我得到了我想要的所有值下一步是创建一个函数,该函数将在我需要的“偏移”处循环:

create or replace
function GetOffsets () 
returns void as $$ 
declare 
-- For this part of the function I only wanted values after 90 million up to 120 million
counter bigint := 90000000;
maxRows bigInt := 120000000;
begin
drop table if exists OffsetValues;
create temp table OffsetValues
(
    offset_myValue bigint
);

while counter <= maxRows loop 
    insert into OffsetValues(offset_myValue)
    select [VALUE-You-need] from just_index where row_number > counter
    limit 1;

    -- here I'm looping every 500,000 records - this is my 'Offset'
    counter := counter + 500000 ;
end loop ;
end ;$$ LANGUAGE plpgsql;

然后运行函数:

select GetOffsets();

再次,一次性的时间量(我从大约 3 分钟获得我的偏移值之一到 3 毫秒获得我的偏移值之一)。然后从临时表中选择:

select * from OffsetValues;

就性能而言,这对我来说非常有效 - 如果我能提供帮助,我认为我不会继续使用偏移量。

希望这可以提高任何较大表的性能。

于 2019-07-01T09:11:14.373 回答