Movatterモバイル変換


[0]ホーム

URL:


Satoshi Yamada, profile picture
Uploaded bySatoshi Yamada
1,354 views

201505 PostgreSQLアンカンファレンス(PL/Pythonで作るWEBアプリ)

2015/05/30に行われたPostgreSQLアンカンファレンスでの資料です。PL/Python + bottle.py でWEBアプリを作る話です

Embed presentation

Download to read offline
PL/Pythonで2層アプリを作ってみたPostgreSQLカンファレンス2015/05アシストセミナールーム
who am i名前:山田 聡会社:アシスト仕事:ポスグレとオラクルのサポートしてます年齢:社会人5年目(ポスグレ4年生)
注意初心者がやってみた系です若干ギャグなので生暖かい目で見てください
9.5 について知りたい方は今直ぐ←
Long Time Ago..
クラサバクライアントとデータベースが直ビジネスロジックはクライアント側中心graph LR id1(クライアントロジック)-->id2(データベース) style id1 fill:#955,stroke:#111,stroke-width:4px; style id2 fill:#559,stroke:#f66,stroke-width:2px;
3層アプリケーション間にWEB/APサーバ増えたクライアント側はブラウザビジネスロジックはWEB/APサーバgraph LR id1(クライアント:ブラウザ)-->id2(WEBサーバ:ロジック) id2-->id3(DB) style id1 fill:#955,stroke:#111,stroke-width:4px; style id2 fill:#555,stroke:#111,stroke-width:4px; style id3fill:#559,stroke:#f66,stroke-width:2px;
でも...管理とか負荷とか速度とか
そうだ2層に戻ろう
できあがったもの
PG2LAYER
PG2LAYERPostgreSQL Two Layer Management System管理用のダッシュボードクエリ結果をJSONで戻すAPIを提供普通のWEBアプリに見える何か
構造PostgreSQLに子プロセスで直接リスニングさせるPL/Pythonを使用Pythonの を利用bottoleフレームワーク
インデント原理主義2系と3系があって過渡期機械学習とか統計学で最近よく見る
def say_hello():    for i in range(1,100):        print "HELLO No %s!" % i
PL/Pythoncreate extensionで追加PythonをPostgreSQLで使えるplpyモジュールでSQLもあつかえる
プレースホルダーを使って実行する場合CREATE FUNCTION pystrip(x text)  RETURNS textAS $$target_query = "select empno from emp where ename=$1"plan = plpy.prepare(target_query,["text"])r_set = plpy.execute(plan, [ "SMITH" ])return r_set[0]["empno"]$$ LANGUAGE plpythonu;直接実行する場合CREATE FUNCTION pl_py_test(x text)  RETURNS textAS $$r_set = plpy.execute("select empno from emp where ename='SMITH'")return r_set[0]["empno"]$$ LANGUAGE plpythonu;
PythonのWEBフレームワーク1ファイルに全てが含まれる最軽量
PG2LAYER 構成でも2層構造graph LR id1(クライアント:ブラウザ)-->id2(DBサーバ:ロジック) style id1 fill:#955,stroke:#111,stroke-width:4px; style id2fill:#555,stroke:#111,stroke-width:4px;
低依存性 (bottole.py /DBLINK / ドライバ不要)低レイヤー (ブラウザ <-> データベース)低管理コスト (DBのバックアップ = APのバックアップ, htmlファイルレス)
起動使用ポートを引数にしてファンクションを起動するだけpg2layer_db=# select start_bottole_httpd(1192);
ソースCREATE OR REPLACE FUNCTION start_bottole_httpd(v_port integer) RETURNS text AS$$"""PG2LAYER ­­ PostgreSQL Two Layer Management System* Low dependency ( only bottole.py , only dblink)* Low layer (browser <­> DB, never AppServer or HTTP Server)* Low manage cost ( backup database backup the Web App)It's Joke Web App.2015/05 sayamada"""import sysimport osimport jsonimport signal# $PGDATA配下に配置したbottole.pyをPYTHONPATHに追加しないといけないのでsys.path.append(os.getcwd()+"/PL_Python_Httpd")from bottle import route, run, template, response, request, get, post, redirect# for DBLINKDB_NAME = "pg2layer_db"DB_USER = "sayamada"DB_HOST = "localhost"
api(select_list,table_name,where_col=None,col=None,col_val=None):URLからクエリを生成しJSONのレスポンスを戻すstatic(content_type,file_name):静的なソース(css/js等)を戻す静的ファイルは表データとして格納get_tmplt(tmplt_name=None):bottoleのテンプレートファイルを戻すほぼHTML表データとして格納do_query_over_dblink(v_query_string):DBLIK経由でSQL処理しJSONで戻す(後述)edit():POSTリクエストに基づきテンプレートを更新
構想1時間作成1日(のはずが1週間)
はまったところ(きっと自分だけ)
問題その1ImportError: No module named bottoleカレントに配置したbottole.pyが読み込めない普通はカレントディレクトリは指定しなくてもいいPostgreSQLの子プロセスは$PGDATAがカレントpg2layer_db=# CREATE OR REPLACE FUNCTION test() RETURNS text ASpg2layer_db­# $$pg2layer_db$# pg2layer_db$# import bottolepg2layer_db$# $$pg2layer_db­# LANGUAGE 'plpythonu' VOLATILE;CREATE FUNCTIONpg2layer_db=# pg2layer_db=# select test();ERROR:  ImportError: No module named bottole CONTEXT:  Traceback (most recent call last):  PL/Python function "test", line 3, in <module>    import bottolePL/Python function "test"
原因PYTHONPATHに$PGDATAが含まれていないjavaのCLASSPATHとかLD_LIBRARY_PATH的なものライブラリを読み込むディレクトリ
対処AP内で動的に$PGDATA配下をPYTHONPATHに追加import sys# $PGDATA配下に配置したbottole.pyをPYTHONPATHに追加sys.path.append(os.getcwd()+"/PL_Python_Httpd")
問題その2トランザクションがCommitできないHTMLソース編集機能を追加フォームからPOSTしたら反映はされるPG2LAYERが異常終了したら変更データが戻る(!?)
PL/Pythonでトランザクション管理をしてもだめだった(というかcommitないし)43.8. 明示的サブトランザクション
原因呼び出し元のstart_bottole_httpdファンクションが終了しないから行った変更はstart_bottole_httpdを正常停止させない限りrollback
対処DBLINKで自律型トランザクションDBLINKでループバックして自律型トランザクションで対応    base_query = "SELECT * FROM dblink('host=%s port=%s dbname=%s user=%s',%s) AS t(r text)"    target_query = "update pg_2_template set src=%s where file_name=%s returning file_name" % (                                                plpy.quote_literal(edit_src),                                                plpy.quote_literal(edit_file_name)                                            )    last_query = base_query % (        DB_HOST,        DB_PORT,        DB_NAME,        DB_USER,        plpy.quote_literal(target_query)    )    r_set = plpy.execute(last_query)
問題3稼動統計が意図せず読み取り一貫性を発揮api()関数で発生pg_stat_activity等がstart_bottole_httpd起動時点の結果しかとれないrepetable read 的な挙動普通の表はちゃんとread commited
原因不明(多分問題2と同じ?)
対処DBLINK稼動統計系だけ分けるもの面倒なのでAPIは全部DBLINK経由に変更
問題4DBLINK経由のクエリで列リストが不定APIでは列リストをURLで指定する実装url query/api/*/hoge -> select * from hoge/api/col1,col2/hoge -> select col1,col2 from hogeDBLINKは戻り値のデータ型を明示しないといけない
対処そうだJSONにしよう元クエリをjson_aggでラップ戻り値はかならずJSONdblink('dbname=pg_2_layer', 'select json_agg(t) from (元クエリ) t')AS t(result json)# DBLINKで自律型トランザクションとする# 型にしばられないため、json_aggでラップしている# 戻りは全部JSONdef do_query_over_dblink(v_query_string):    # DBLINKの大枠    base_query = "SELECT * FROM dblink('host=%s port=%s dbname=%s user=%s', %s) AS t(result json)    last_query = base_query % (        DB_HOST,        DB_PORT,        DB_NAME,        DB_USER,        plpy.quote_literal("select json_agg(t) from (" + v_query_string+ ") t") # クエリも引数なので    )    plpy.log( last_query)    r_set = plpy.execute(last_query)    plpy.log(r_set)    # jsonで戻しても取得時はstrになってたのでstrとして統一    result_json_str = "[]"    if r_set[0]["result"] is not None:        result_json_str = r_set[0]["result"]    # 利用側の利便性を考えてjsonで戻す
元のクエリをselect * from empjson_aggでラップしてselect json_agg(t) from (    select * from emp) tdblinkでラップするselect * from dblink('    select json_agg(t) json from (        select * from emp    ) t') AS t(result json)
こんだけラップで何がパフォーマンスか
問題5停止できないstart_bottole_httpdが止められないctrl+c/pg_terminate_backendできず
ctrl+cpg2layer_db=# select start_bottole_httpd(1192);^CCancel request sent
ctrl+cpg2layer_db=# select start_bottole_httpd(1192);^CCancel request sent^CCancel request sent
ctrl+cpg2layer_db=# select start_bottole_httpd(1192);^CCancel request sent^CCancel request sent^CCancel request sent
ctrl+cpg2layer_db=# select start_bottole_httpd(1192);^CCancel request sent^CCancel request sent^CCancel request sent^CCancel request sent
落ちないorz
原因実行中はpostgresqlのコンテキストではなくPythonのコンテキストシグナルハンドラがPythonコンテキストで動作してない?
対処自分でシグナルハンドラ書くPythonコンテキストでSIGINTを処理するように受け取ったら落ちるdef signal_handler(num, frame):    plpy.log("SIGINT_restart")    sys.exit(0)signal.signal(signal.SIGINT, signal_handler)run(host='0.0.0.0', port=v_port)
いないと思いますがPL/Pythonを使ったWEBアプリを作成されようと思っている方の一助になれば幸いです。
終わり

Recommended

PDF
形態素解析器 MeCab の新語・固有表現辞書 mecab-ipadic-NEologd のご紹介
PDF
PL/Pythonで独自の集約関数を作ってみる
PDF
PostgreSQLではじめるOSS開発@OSC 2014 Hiroshima
PDF
PostgreSQL10徹底解説
PDF
comp_pfiseminar
PDF
CRF を使った Web 本文抽出
PDF
PostgreSQLのパラレル化に向けた取り組み@第30回(仮名)PostgreSQL勉強会
PPTX
都市工学調査資料
PDF
DBエンジニアに必要だったPythonのスキル
PDF
bottleで始めるWEBアプリの最初の一歩
PDF
Djangoで業務改善したい
PDF
PostgreSQLとPythonとSQL
PDF
本気でPythonで宛名書きした話
PDF
pythonでemlファイルを扱う話
PDF
10080分でPythonからIP Messeneger
PDF
bottle.pyをつかったチャットアプリ作成チュートリアル
PDF
15分で情シスに怒られる方法
PDF
PostgreSQL SQLチューニング入門 実践編(pgcon14j)
PDF
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PDF
PostgreSQL実行計画入門@関西PostgreSQL勉強会
PDF
Requestsで始める5分前帰社
PDF
Pythonで業務改善をしたときにあった問題(ライト版)
PDF
PythonでテキストをJSONにした話(PyCon mini sapporo 2015)

More Related Content

PDF
形態素解析器 MeCab の新語・固有表現辞書 mecab-ipadic-NEologd のご紹介
PDF
PL/Pythonで独自の集約関数を作ってみる
PDF
PostgreSQLではじめるOSS開発@OSC 2014 Hiroshima
PDF
PostgreSQL10徹底解説
PDF
comp_pfiseminar
PDF
CRF を使った Web 本文抽出
PDF
PostgreSQLのパラレル化に向けた取り組み@第30回(仮名)PostgreSQL勉強会
PPTX
都市工学調査資料
形態素解析器 MeCab の新語・固有表現辞書 mecab-ipadic-NEologd のご紹介
PL/Pythonで独自の集約関数を作ってみる
PostgreSQLではじめるOSS開発@OSC 2014 Hiroshima
PostgreSQL10徹底解説
comp_pfiseminar
CRF を使った Web 本文抽出
PostgreSQLのパラレル化に向けた取り組み@第30回(仮名)PostgreSQL勉強会
都市工学調査資料

More from Satoshi Yamada

PDF
DBエンジニアに必要だったPythonのスキル
PDF
bottleで始めるWEBアプリの最初の一歩
PDF
Djangoで業務改善したい
PDF
PostgreSQLとPythonとSQL
PDF
本気でPythonで宛名書きした話
PDF
pythonでemlファイルを扱う話
PDF
10080分でPythonからIP Messeneger
PDF
bottle.pyをつかったチャットアプリ作成チュートリアル
PDF
15分で情シスに怒られる方法
PDF
PostgreSQL SQLチューニング入門 実践編(pgcon14j)
PDF
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PDF
PostgreSQL実行計画入門@関西PostgreSQL勉強会
PDF
Requestsで始める5分前帰社
PDF
Pythonで業務改善をしたときにあった問題(ライト版)
PDF
PythonでテキストをJSONにした話(PyCon mini sapporo 2015)
DBエンジニアに必要だったPythonのスキル
bottleで始めるWEBアプリの最初の一歩
Djangoで業務改善したい
PostgreSQLとPythonとSQL
本気でPythonで宛名書きした話
pythonでemlファイルを扱う話
10080分でPythonからIP Messeneger
bottle.pyをつかったチャットアプリ作成チュートリアル
15分で情シスに怒られる方法
PostgreSQL SQLチューニング入門 実践編(pgcon14j)
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PostgreSQL実行計画入門@関西PostgreSQL勉強会
Requestsで始める5分前帰社
Pythonで業務改善をしたときにあった問題(ライト版)
PythonでテキストをJSONにした話(PyCon mini sapporo 2015)

201505 PostgreSQLアンカンファレンス(PL/Pythonで作るWEBアプリ)


[8]ページ先頭

©2009-2025 Movatter.jp