我在表格中有超过1000万条记录。
SELECT * FROM tbl ORDER BY datecol DESC
LIMIT 10
OFFSET 999990
explain.depesz.com上EXPLAIN ANALYZE
的输出
执行上述查询大约需要10秒钟。我怎样才能让它更快?
使用子查询将执行时间缩短一半:
SELECT * FROM tbl where id in
(SELECT id FROM tbl ORDER BY datecol DESC LIMIT 10 OFFSET 999990)
在explain.depesz.com上输出EXPLAIN ANALYZE
。
答案 0 :(得分:2)
您需要在ORDER BY
中使用的列上创建索引。理想情况下,排序顺序相同,但PostgreSQL可以以几乎相同的速度向后扫描索引。
CREATE INDEX tbl_datecol_idx ON tbl (datecol DESC);
当前手册中有更多about indexes和CREATE INDEX
使用EXPLAIN ANALYZE
进行测试以获取查询计划之外的实际时间。
答案 1 :(得分:0)
我试图用一个很大的表(> 100m条记录)做类似的事情,发现使用Offset / Limit会降低性能。 前10m个记录的偏移量(限制为1)约为1.5分钟,并且以指数方式增长。 记录到5000万,我每次选择最多需要3分钟-甚至使用子查询。
我遇到了一条帖子here which details useful alternatives。
我对此做了些微修改以满足自己的需求,并想出了一种方法,可以使我快速获得结果。
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;
就性能而言,这对我来说真的非常好-如果可以,我认为我不会使用偏移量。
希望这可以提高任何较大表的性能。