[pgsql-jp: 36927] Re: 項目毎に件数指定をしたい
Yasuhiro Shibutani
yasuhiro_shibutani @ ybb.ne.jp
2006年 3月 26日 (日) 20:41:17 JST
渋谷です。
> > "ID" が一意なテーブルはないんでしょうか?
> > あるならそちらのテーブルにクエリかけた方がいいです。
> > ないなら作ったほうがいいです。^^;
> ここで質問させて頂いた"ID"ですが、実際のテーブルでは
> 日付(yyyy/mm/dd)を to_char( hiduke ,'yyyy/mm')としているので
> これもコストがかかっているせいなんでしょうね。
> #実は今まで、こういうコスト意識していませんでした
なるほど、これは想像つきませんでした。
しかし、これなら例え10年分出力する場合であっても
120回しか内側のクエリを実行しないことになりますね。
例えば次のような感じではダメでしょうか。
CREATE OR REPLACE FUNCTION "public"."rank_table1_f1" (
"_t1" timestamptz,
"_t2" timestamptz,
"_top_n" integer
) RETURNS SETOF "public"."table1" AS
$body$
DECLARE
"_t" timestamptz;
"_ret" "table1"%ROWTYPE;
BEGIN
"_t" := date_trunc('month', "_t1");
WHILE (
"_t" BETWEEN
date_trunc('month', "_t1") AND
date_trunc('month', "_t2")
) LOOP
FOR "_ret" IN
SELECT * FROM "table1"
WHERE "hiduke" = "_t"
ORDER BY "f1" DESC
LIMIT "_top_n"
LOOP
RETURN NEXT "_ret";
END LOOP;
IF ("_t1" < "_t2") THEN
"_t" := "_t" + interval '1 month';
ELSE
"_t" := "_t" - interval '1 month';
END IF;
END LOOP;
RETURN;
END;
$body$
LANGUAGE 'plpgsql'
STABLE CALLED ON NULL INPUT
SECURITY INVOKER;
内側のクエリの無駄打ちが発生するかもしれませんが、
インデックスが張ってあればコストは大してかかりません。
(少なくとも以前のものよりは低コストだと思います。)
hiduke フィールドに「式に対するインデックス」があれば
なお良いですね。
On Sat, 25 Mar 2006 14:59:12 +0900
西村 篤史 <a2c @ lets-heart.co.jp> wrote:
> 西村@和歌山市です。
>
> Yasuhiro Shibutani wrote:
> > 渋谷です。
> > # もういいのかもしれませんが。。。
> いえいえ、ありがとうございます(^^
>
> >>渋谷さんのを実行してみますと、項目ごとに30行表示で44.7秒と
> > 実際のテーブル定義やデータが分からないのでハッキリとはいえませんが、
> > まだまだ遅いと思いますね。
>
> お、遅いですか(苦笑
>
> > "ID" が一意なテーブルはないんでしょうか?
> > あるならそちらのテーブルにクエリかけた方がいいです。
> > ないなら作ったほうがいいです。^^;
> ここで質問させて頂いた"ID"ですが、実際のテーブルでは
> 日付(yyyy/mm/dd)を to_char( hiduke ,'yyyy/mm')としているので
> これもコストがかかっているせいなんでしょうね。
> #実は今まで、こういうコスト意識していませんでした
>
>
> > 浅見です。
> > PostgreSQL 8.0からは、sort_memではなくwork_memを利用するのが
> > 一般的です。(7.xでsort_memだったものが8.0でwork_memに名前が変
> > わりました)
> そういう事だったんですね。早速やってみました。
> 本では目にしていた「コスト」ですが、考えさせられる一件でした。
>
> 渋谷さん、浅見さん、ありがとうございました。
--
Yasuhiro Shibutani <yasuhiro_shibutani @ ybb.ne.jp>
pgsql-jp メーリングリストの案内