PostgreSQLに関するTipsをメモ。
DB作成、ユーザ作成、デフォルト権限付与、スキーマへの権限付与
dbaユーザとappユーザを作って、appユーザにデフォルト権限を設定する。
詳細はこちらを参照のこと。
psql -U postgres
=> -- ユーザ作成
=> create user hoge_dba password 'hoge_dba';
=> create user hoge_app password 'hoge_app';
=> -- DB作成
=> create database hoge owner hoge_dba;
=> -- デフォルト権限付与
=> alter default privileges in schema public grant all on tables to hoge_app;
=> alter default privileges in schema public grant all on sequences to hoge_app;
=> alter default privileges in schema public grant all on functions to hoge_app;
=> -- スキーマへの権限付与
=> grant all on schema public to hoge_app; -- スキーマへの権限がないとそもそもそのスキーマないのオブジェクトが見えない
=> grant select on all tables in schema public to hoge_app; -- 既存テーブルへのアクセス権限
seq scanやindex scanの回数、フェッチ数等を確認
select * from pg_stat_user_tables
ロック中のプロセスを取得
select
l.pid
, db.datname
, c.relname
, l.locktype
, l.mode
from
pg_locks l
left join pg_class c on (l.relation=c.relfilenode)
left join pg_database db on (l.database = db.oid ORDER BY l.pid)
プロセスをkillする(super userのみ)
select pg_terminate_backend(${pid});
実行中SQLを探す
full SQLが見たい場合はsrc/include/pgstat.h
の PGSTAT_ACTIVITY_SIZEを変更するらしい
select
procpid
, start
, now() - start as lap
, current_query
from
(
select
backendid
, pg_stat_get_backend_pid(s.backendid) as procpid
, pg_stat_get_backend_activity_start(s.backendid) as start
, pg_stat_get_backend_activity(s.backendid) as current_query
from
(select pg_stat_get_backend_idset() as backendid) as s
) as s
where
current_query <> '<IDLE>'
order by
start
最後にAnalyzeした日時を確認
select
relname, n_live_tup, n_dead_tup, last_vacuum, last_autovacuum, last_analyze, last_autoanalyze, schemaname
from
pg_stat_all_tables
where
schemaname = 'hoge'
order by
relname;
インデックスの容量確認
select
*, pg_size_pretty(pg_relation_size(indexrelid))
from
pg_stat_user_indexes
where
idx_scan = 0
and idx_tup_read = 0
and idx_tup_fetch = 0
order by
pg_size_pretty desc
レコードロックせずindex作成
create index concurrently
現在のシーケンス番号確認
select last_value from hoge_seq
シーケンス番号をリセットする
alter sequence hoge_seq restart with 次に取得したい番号
再起SQLのサンプル
2016/06/01から現在までの7日毎の日付リストを生成
with recursive tmp(day) as (
values (to_timestamp('201606', 'YYYYMM'))
-- ↑は select to_timestamp('201606', 'YYYYMM') と同義
union all
select
day + '7days'
from
tmp
where
day + '5days' <= current_timestamp
)
select * from tmp;
文字列をsplitしてテーブルや配列に展開する
-- テーブルへ展開
select regexp_split_to_table('aaa,bbb,ccc', ',');
> "aaa"
> "bbb"
> "ccc"
-- 配列へ展開
select regexp_split_to_array('aaa,bbb,ccc', ',');
> "{aaa,bbb,ccc}"
json配列をテーブルに展開する
lateralをつけるとその関数やサブクエリが、同列の関数やサブクエリよりもあとに実行されるので、他のサブクエリの結果をつかえるようになる
with fuga_table as (
select
h.id
, h.name
, cast(value->'def_id' as text) as def_id
, cast(value->'def_name' as text) as def_name
, cast(value->'def_type' as text) as def_type
from
hoge h,
lateral json_array_elements(h.fuga_json::json)
where
h.id < 1000
)
select
*
from
fuga_table
where
def_type = '"text"'
ダンプ & リストア
## dump
# connection_option -> optionの順番
# -F: フォーマット指定 p: plainなSQL, c: カスタムアーカイブ(バイナリ。サイズが小さい)
# -t: 対象テーブルを指定
# -s: DDLだけ出力
# -a: データのみ出力
# --column-inserts カラム名付きinsert文
pg_dump -h {host} -p {port} -U {user} -d {db} -t {table_name} -Fc -f hoge.dmp
## restore
# connection_option -> optionの順番
# optionの内容はpg_dumpとほぼ同じ
pg_restore -h {host} -p {port} -U {user} -d {db} -t {table_name} -Fc hoge.dmp
CSVエクスポート & CSVインポート
psqlのcopyコマンドを利用する方法を記載する
## CSVエクスポート
psql -h {host} -p {port} -U {user} -d {db}
=> \copy {table_name} to '{csv_path}' with csv delimiter ','
## CSVインポイート
psql -h {host} -p {port} -U {user} -d {db}
=> \copy {table_name} (column_names,...) from '{csv_path}' with csv
データフォルダパスの確認
ps aux | grep postgres
-> -Dの後ろがデータフォルダ
pg_hba.confの反映
## 設定ファイルを再読み込みする
pg_ctl reload -D {データフォルダパス}
## postgresql自体を再起動する(serviceコマンドで起動している場合)
service postgresql restart
スキーマ検索パス(search_path)の設定
スキーマ名.オブジェクト名
で完全修飾することもできますが、スキーマ名で記載しない場合、スキーマ検索パスに指定されてるスキーマを順番に参照します。
常にスキーマ名で修飾するのは大変なので、スキーマ検索パスを設定する方法を記載します。
psql -h {host} -p {port} -U {user} -d {db}
=> -- search_pathを確認する
=> show search_path;
search_path
-----------------
"$user", public
(1 row)
=> -- セッション内でsearch_pathを設定する
=> set search_path = "hoge", "$user", public;
SET
=> -- ユーザのsearch_pathを設定する
=> alter user {user} set search_path to "hoge", "$user", public;
ALTER ROLE