次のタイプのデータを含むテーブルがあります。
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 行が含まれていますが、100 万行またはそれ以上になる可能性があります。それでも、今のところ、100K マーク前後にとどまっていると仮定しましょう。
これらのテーブルから、1 つの 2 つの条件が満たされる行を選択しようとしています。
- 特定のサブセットにあるすべての行
n_place_id
(この部分は簡単です)。また - 他のすべての
n_place_id
値については、最初の 10 行がソートされますdt_modified
(ここがより複雑になります)。
1 つの 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 つのテーブルに追加する必要があり、追加の条件を適用し、さらに並べ替えを適用する必要があることを考えると、これは明らかに受け入れられません。
まあ、まだこのデータを取得する必要があるので、関数に何かが欠けているか、アルゴリズム全体を再考する必要があります。いずれにせよ、これについては助けが必要です。