Upload
toshi-harada
View
242
Download
1
Embed Size (px)
DESCRIPTION
PostgreSQL Function Volatility Categories.
Citation preview
関数の変動性分類について
おさらいしてみる
ぬこ@横浜 (@nuko_yokohama)
久々に
みなさんこんにちは今日も PostgreSQL
拡張ライフを楽しんでますか?
さて、拡張の基本は「関数」です。
SQLplpgsqlC 言語
どんな言語で作っても
留意すべき点がある。
それが関数の変動性分類
CREATE FUNCTION で関数登録時に
指定するパラメータ
IMMUTABLESTABLE
VOLATILE
IMMUTABLESTABLE
VOLATILE
イミュータボォ
同一引数に対する呼び出しは
常に同一の結果を返すことを保証
データベース更新不可
IMMUTABLE 関数例postgres=# BEGIN;BEGINpostgres=# SELECT lower('ABC DEF'); lower --------- abc def(1 row)
postgres=# SELECT lower('ABC DEF'); lower --------- abc def(1 row)
postgres=# COMMIT;COMMITpostgres=# SELECT lower('ABC DEF'); lower --------- abc def(1 row)
同じ引数を与えれば同じ値が必ず返却される
IMMUTABLESTABLE
VOLATILE
ステーボォ
同一の文で同一引数に対する呼び出しは
常に同一結果を返すことを保証設定により値が変動
データベース更新不可
STABLE 関数例postgres=# BEGIN;BEGINpostgres=# SELECT now(); now ------------------------------- 2014-11-03 10:31:30.161264+09(1 row)
postgres=# SELECT now(); now ------------------------------- 2014-11-03 10:31:30.161264+09(1 row)
postgres=# SET TIMEZONE='GMT';SETpostgres=# SELECT now(); now ------------------------------- 2014-11-03 01:31:30.161264+00(1 row)
同一トランザクション内では同じ値を返す
PostgreSQL 設定で値が変動する
IMMUTABLESTABLE
VOLATILEヴォラタィ
同一引数で続けて呼び出して異なる結果を返却しても良い。
データベースへの変更を許容
CREATE FUNCTON のデフォルトはこれ。
VOLATILE 関数例test=# BEGIN;BEGINtest=# SELECT random(); random ------------------- 0.472748554777354(1 row)
test=# SELECT random(); random ------------------- 0.646271407604218(1 row)
test=# END;COMMIT
VOLATILE 関数例
関数の変動性分類て何の役に立つの?
PostgreSQL の最適化
例:定数と演算子bench=# EXPLAIN SELECT aid, bid, abalance FROM pgbench_accounts WHERE aid = 10 - 3 * 2; QUERY PLAN ----------------------------------------------------------------------------------------------- Index Scan using pgbench_accounts_pkey on pgbench_accounts (cost=0.29..8.31 rows=1 width=12) Index Cond: (aid = 4) Planning time: 0.080 ms(3 rows)
算術演算子はIMUUTABLE関数
実行計画作成時に定数演算結果で評価
例: VOLATILE
bench=# EXPLAIN SELECT aid,bid FROM pgbench_accounts WHERE aid = (random() * 10)::int; QUERY PLAN ------------------------------------------------------------------- Seq Scan on pgbench_accounts (cost=0.00..3640.00 rows=1 width=8) Filter: (aid = ((random() * 10::double precision))::integer) Planning time: 1.095 ms(3 rows)
random()はVOLATILE関数
その行の値を必要とするすべての行においてその関数を再評価
インデックスは使えない
もうひとつ関数を使う側で留意しなければいけないこと
式インデックス
式インデックスに使われる関数は
IMMUTABLE 必須
意外な関数がIMMUTABLE でなく
STABLE で困る
例: TO_NUMBERtest=# \d book Table "public.book" Column | Type | Modifiers --------+---------+----------- id | integer | name | text | price | text |
test=# TABLE book; id | name | price ----+------------------+------- 1 | 吾輩はぬこである | 1,320 2 | 働けメロス | 680 3 | 群馬英雄伝説(1) | 1,980(3 rows)
priceが TEXT型になっている。
まれによくある(笑)
正しく大小比較を行なうために
TO_NUMBERを使おう
例: TO_NUMBERtest=# SELECT name, price FROM book WHERE to_number(price, '9999.') > 1000; name | price ------------------+------- 吾輩はぬこである | 1,320 群馬英雄伝説(1) | 1,980(2 rows)
test=# CREATE INDEX price_idx ON book USING btree ((to_number(price, '9999.')));ERROR: functions in index expression must be marked IMMUTABLEtest=#
数値による正しい評価が出来た!じゃ、式インデックス化できんじゃね?
TO_NUMBERはIMMUTABEじゃない
(STABLE)から式インデックスとして使えない (´・ω・` )
BAD ノウハウだがこういうときにはIMMUTABLE な
ラッパ関数で対処
例: TO_NUMBERtest=# CREATE FUNCTION my_to_number(text, text) RETURNS numeric AS 'SELECT to_number($1, $2)' LANGUAGE SQL IMMUTABLE;CREATE FUNCTIONtest=# CREATE INDEX price_idx ON book USING btree ((my_to_number(price, '9999.')));CREATE INDEXtest=# \d book Table "public.book" Column | Type | Modifiers --------+---------+----------- id | integer | name | text | price | text | Indexes: "price_idx" btree (my_to_number(price, '9999.'::text))
IMMUTABLEなラッパ関数を作成
式インデックスにさっき作ったラッパ関数を使う
あくまでも非常手段!
ざっくりまとめ関数変動性 IMMUTABLE STABLE VOLATILE
データベースへの変更
不可 不可 可能
最適化 最適化される複数関数呼び出しの集約定数の畳み込み
最適化される複数関数呼び出しの集約
最適化されない
式インデックス 使用可能 使用不可 使用不可
スナップショット 問い合わせ開始時点
問い合わせ開始時点
処理中の実行時点
おまけ各 SQL 関数の関数変動性分類の検索
postgres=# SELECT proname, provolatile FROM pg_proc; proname | provolatile ----------------------------------------------+------------- boolin | i(中略) regprocin | s(中略) timeofday | v(中略)postgres=#
i:IMMUTABLEs:STABLE,
v:VOLATILE
おしまい
参考リンク35.6. 関数の変動性分類http://www.postgresql.jp/document/9.3/html/xfunc-volatility.html
11.7. 式に対するインデックスhttp://www.postgresql.jp/document/9.3/html/indexes-expressional.html
CREATE FUNCTIONhttp://www.postgresql.jp/document/9.3/html/sql-createfunction.html