lt 関数の変動性分類についておさらいしてみる。

33
関数の変動性分類に ついて おさらいしてみる ぬこ@横浜 (@nuko_yokohama) 久々に

Upload: toshi-harada

Post on 22-Jun-2015

242 views

Category:

Technology


1 download

DESCRIPTION

PostgreSQL Function Volatility Categories.

TRANSCRIPT

Page 1: Lt 関数の変動性分類についておさらいしてみる。

関数の変動性分類について

おさらいしてみる

ぬこ@横浜 (@nuko_yokohama)

久々に

Page 2: Lt 関数の変動性分類についておさらいしてみる。

みなさんこんにちは今日も PostgreSQL

拡張ライフを楽しんでますか?

Page 3: Lt 関数の変動性分類についておさらいしてみる。

さて、拡張の基本は「関数」です。

Page 4: Lt 関数の変動性分類についておさらいしてみる。

SQLplpgsqlC 言語

Page 5: Lt 関数の変動性分類についておさらいしてみる。

どんな言語で作っても

留意すべき点がある。

Page 6: Lt 関数の変動性分類についておさらいしてみる。

それが関数の変動性分類

Page 7: Lt 関数の変動性分類についておさらいしてみる。

CREATE FUNCTION で関数登録時に

指定するパラメータ

Page 8: Lt 関数の変動性分類についておさらいしてみる。

IMMUTABLESTABLE

VOLATILE

Page 9: Lt 関数の変動性分類についておさらいしてみる。

IMMUTABLESTABLE

VOLATILE

イミュータボォ

Page 10: Lt 関数の変動性分類についておさらいしてみる。

同一引数に対する呼び出しは

常に同一の結果を返すことを保証

データベース更新不可

Page 11: Lt 関数の変動性分類についておさらいしてみる。

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)

同じ引数を与えれば同じ値が必ず返却される

Page 12: Lt 関数の変動性分類についておさらいしてみる。

IMMUTABLESTABLE

VOLATILE

ステーボォ

Page 13: Lt 関数の変動性分類についておさらいしてみる。

同一の文で同一引数に対する呼び出しは

常に同一結果を返すことを保証設定により値が変動

データベース更新不可

Page 14: Lt 関数の変動性分類についておさらいしてみる。

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 設定で値が変動する

Page 15: Lt 関数の変動性分類についておさらいしてみる。

IMMUTABLESTABLE

VOLATILEヴォラタィ

Page 16: Lt 関数の変動性分類についておさらいしてみる。

同一引数で続けて呼び出して異なる結果を返却しても良い。

データベースへの変更を許容

CREATE FUNCTON のデフォルトはこれ。

Page 17: Lt 関数の変動性分類についておさらいしてみる。

VOLATILE 関数例test=# BEGIN;BEGINtest=# SELECT random(); random ------------------- 0.472748554777354(1 row)

test=# SELECT random(); random ------------------- 0.646271407604218(1 row)

test=# END;COMMIT

VOLATILE 関数例

Page 18: Lt 関数の変動性分類についておさらいしてみる。

関数の変動性分類て何の役に立つの?

Page 19: Lt 関数の変動性分類についておさらいしてみる。

PostgreSQL の最適化

Page 20: Lt 関数の変動性分類についておさらいしてみる。

例:定数と演算子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関数

実行計画作成時に定数演算結果で評価

Page 21: Lt 関数の変動性分類についておさらいしてみる。

例: 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関数

その行の値を必要とするすべての行においてその関数を再評価

インデックスは使えない

Page 22: Lt 関数の変動性分類についておさらいしてみる。

もうひとつ関数を使う側で留意しなければいけないこと

Page 23: Lt 関数の変動性分類についておさらいしてみる。

式インデックス

Page 24: Lt 関数の変動性分類についておさらいしてみる。

式インデックスに使われる関数は

IMMUTABLE 必須

Page 25: Lt 関数の変動性分類についておさらいしてみる。

意外な関数がIMMUTABLE でなく

STABLE で困る

Page 26: Lt 関数の変動性分類についておさらいしてみる。

例: 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を使おう

Page 27: Lt 関数の変動性分類についておさらいしてみる。

例: 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)から式インデックスとして使えない (´・ω・` )

Page 28: Lt 関数の変動性分類についておさらいしてみる。

BAD ノウハウだがこういうときにはIMMUTABLE な

ラッパ関数で対処

Page 29: Lt 関数の変動性分類についておさらいしてみる。

例: 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なラッパ関数を作成

式インデックスにさっき作ったラッパ関数を使う

あくまでも非常手段!

Page 30: Lt 関数の変動性分類についておさらいしてみる。

ざっくりまとめ関数変動性 IMMUTABLE STABLE VOLATILE

データベースへの変更

不可 不可 可能

最適化 最適化される複数関数呼び出しの集約定数の畳み込み

最適化される複数関数呼び出しの集約

最適化されない

式インデックス 使用可能 使用不可 使用不可

スナップショット 問い合わせ開始時点

問い合わせ開始時点

処理中の実行時点

Page 31: Lt 関数の変動性分類についておさらいしてみる。

おまけ各 SQL 関数の関数変動性分類の検索

postgres=# SELECT proname, provolatile FROM pg_proc; proname | provolatile ----------------------------------------------+------------- boolin | i(中略) regprocin | s(中略) timeofday | v(中略)postgres=#

i:IMMUTABLEs:STABLE,

v:VOLATILE

Page 32: Lt 関数の変動性分類についておさらいしてみる。

おしまい

Page 33: Lt 関数の変動性分類についておさらいしてみる。

参考リンク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