我有一个包含以下类型数据的表:
create table store (
n_id serial not null primary key,
n_place_id integer not null references place(n_id),
dt_modified timestamp not null,
t_tag varchar(4),
n_status integer not null default 0
...
(about 50 more fields)
);
在下面的查询中使用的 n_id、n_place_id、dt_modified 和所有其他字段都有索引。
该表目前包含大约 100,000 行,但可能会增长到接近一百万甚至更多。然而,现在让我们假设我们保持在 100K 左右。
我正在尝试从这些表中选择满足两个条件的行:
n_place_id
位于特定子集中的所有行(这部分很简单);或者- 对于所有其他
n_place_id
值,前十行排序依据dt_modified
(这是变得更加复杂的地方)。
在一个 SQL 中做这件事似乎太痛苦了,所以我很高兴有一个存储函数。我的函数是这样定义的:
create or replace function api2.fn_api_mobile_objects()
returns setof store as
$body$
declare
maxres_free integer := 10;
resulter store%rowtype;
mcnt integer := 0;
previd integer := 0;
begin
create temporary table paid on commit drop as
select n_place_id from payments where t_reference is not null and now()::date between dt_paid and dt_valid;
for resulter in
select * from store where n_status > 0 and t_tag is not null order by n_place_id, dt_modified desc
loop
if resulter.n_place_id in (select n_place_id from paid) then
return next resulter;
else
if previd <> resulter.n_place_id then
mcnt := 0;
previd := resulter.n_place_id;
end if;
if mcnt < maxres_free then
return next resulter;
mcnt := mcnt + 1;
end if;
end if;
end loop;
end;$body$
language 'plpgsql' volatile;
问题是
select * from api2.fn_api_mobile_objects()
执行大约需要 6-7 秒。考虑到之后需要将此结果集join
编辑到其他 3 个表,并应用一堆附加条件并应用进一步排序,这显然是不可接受的。
好吧,我仍然需要获取这些数据,所以要么我在函数中遗漏了一些东西,要么我需要重新考虑整个算法。不管怎样,我需要这方面的帮助。