# Postgresql 經驗談
資料維度 每天1-10萬筆資料
```sql
CREATE TABLE public.goods_plan_user_mapping_1029 (
id bigserial NOT NULL,
daily date NOT NULL,
user_id int8 NOT NULL,
goods_plan_daily_id int8 NOT NULL,
created_at int8 NULL,
account text NULL,
"operator" text NULL,
superior_account text NULL,
CONSTRAINT goods_plan_user_mapping_1029_pkey PRIMARY KEY (daily, goods_plan_daily_id, user_id)
)
PARTITION BY LIST (daily);
CREATE INDEX goods_plan_user_mapping_1029_daily_idx ON ONLY public.goods_plan_user_mapping_1029 USING btree (daily);
CREATE INDEX goods_plan_user_mapping_1029_idx ON ONLY public.goods_plan_user_mapping_1029 USING btree (goods_plan_daily_id);
```
資料維度每天 5筆資料
```sql
CREATE TABLE public.goods_plan_daily (
id bigserial NOT NULL,
site_id int8 NOT NULL,
daily date NOT NULL,
"name" text NULL,
members int8 NOT NULL DEFAULT 0,
normal_max_balance_ratio numeric(19, 2) NULL DEFAULT 0,
normal_min_balance_ratio numeric(19, 2) NULL DEFAULT 0,
exceed_probability numeric(19, 2) NULL DEFAULT 0,
exceed_max_balance_ratio numeric(19, 2) NULL DEFAULT 0,
exceed_min_balance_ratio numeric(19, 2) NULL DEFAULT 0,
plan jsonb NULL,
task_limit jsonb NULL,
"operator" text NULL,
created_at int8 NULL,
task_reward_ratio numeric(19, 4) NULL DEFAULT 0,
updated_at int8 NULL,
contract_id int8 NULL,
CONSTRAINT goods_plan_daily_pk PRIMARY KEY (id, daily)
)
PARTITION BY LIST (daily);
CREATE INDEX goods_plan_daily_idx ON ONLY public.goods_plan_daily USING btree (site_id, daily);
```
```sql
SELECT user_id FROM goods_plan_user_mapping_1029 WHERE daily = (SELECT daily FROM goods_plan_daily WHERE id = 2572 AND site_id = 1029)
```
事實上這是cross join,表會做cross join後再filter。
1. 空資料表也會影響效能 (175天份=> 7天) (160s => 1s)
2. 思考表需不需要做partition
``` sql
Aggregate (cost=30549.26..30549.27 rows=1 width=8) (actual time=74.388..74.404 rows=1 loops=1)
-> Hash Right Join (cost=30500.50..30519.59 rows=11866 width=0) (actual time=74.339..74.398 rows=28 loops=1)
Hash Cond: (td.user_id = ub.user_id)
-> Seq Scan on time_deposit_deposit_cache_log_1029 td (cost=0.00..15.60 rows=560 width=8) (actual time=0.002..0.002 rows=0 loops=1)
-> Hash (cost=30352.18..30352.18 rows=11866 width=8) (actual time=74.327..74.342 rows=28 loops=1)
Buckets: 16384 Batches: 1 Memory Usage: 130kB
-> Hash Right Join (cost=30334.71..30352.18 rows=11866 width=8) (actual time=74.276..74.335 rows=28 loops=1)
Hash Cond: (pa.user_id = ub.user_id)
-> Seq Scan on preferential_interest_deposit_cache_log_1029 pa (cost=0.00..14.60 rows=460 width=8) (actual time=0.007..0.007 rows=0 loops=1)
-> Hash (cost=30186.39..30186.39 rows=11866 width=8) (actual time=74.253..74.267 rows=28 loops=1)
Buckets: 16384 Batches: 1 Memory Usage: 130kB
-> Hash Join (cost=29142.05..30186.39 rows=11866 width=8) (actual time=67.734..74.256 rows=28 loops=1)
Hash Cond: (ub.user_id = u.id)
-> Seq Scan on users_balance ub (cost=0.00..918.88 rows=47788 width=8) (actual time=0.007..4.516 rows=47790 loops=1)
-> Hash (cost=28990.86..28990.86 rows=12095 width=8) (actual time=66.322..66.335 rows=28 loops=1)
Buckets: 16384 Batches: 1 Memory Usage: 130kB
-> Seq Scan on users u (cost=13193.51..28990.86 rows=12095 width=8) (actual time=22.980..66.322 rows=28 loops=1)
Filter: (((agent_type)::text = ANY ('{agt1}'::text[])) AND (NOT (hashed SubPlan 1)) AND (NOT (hashed SubPlan 3)) AND (site_id = 1029))
Rows Removed by Filter: 47762
SubPlan 1
-> Seq Scan on goods_contract_user_1029 (cost=0.00..6.58 rows=70 width=8) (actual time=0.005..0.030 rows=98 loops=1)
Filter: ((status = 0) OR ((status = 1) AND (expired_at > '1665642134175'::bigint)))
SubPlan 3
-> Append (cost=48.57..12200.41 rows=394541 width=8) (actual time=0.007..9.543 rows=47380 loops=1)
InitPlan 2 (returns $1)
-> Append (cost=0.00..48.57 rows=21 width=4) (actual time=0.069..0.098 rows=1 loops=1)
-> Seq Scan on goods_plan_daily_2022_10_01 (cost=0.00..1.03 rows=1 width=4) (actual time=0.005..0.006 rows=0 loops=1)
Filter: ((id = 2572) AND (site_id = 1029))
Rows Removed by Filter: 2
-> Seq Scan on goods_plan_daily_2022_10_02 (cost=0.00..2.17 rows=1 width=4) (actual time=0.006..0.006 rows=0 loops=1)
Filter: ((id = 2572) AND (site_id = 1029))
Rows Removed by Filter: 11
-> Index Scan using goods_plan_daily_2022_10_03_pkey on goods_plan_daily_2022_10_03 (cost=0.14..2.37 rows=1 width=4) (actual time=0.007..0.008 rows=0 loops=1)
Index Cond: (id = 2572)
Filter: (site_id = 1029)
-> Index Scan using goods_plan_daily_2022_10_04_pkey on goods_plan_daily_2022_10_04 (cost=0.27..2.49 rows=1 width=4) (actual time=0.005..0.005 rows=0 loops=1)
Index Cond: (id = 2572)
Filter: (site_id = 1029)
-> Index Scan using goods_plan_daily_2022_10_05_pkey on goods_plan_daily_2022_10_05 (cost=0.28..2.50 rows=1 width=4) (actual time=0.006..0.007 rows=0 loops=1)
Index Cond: (id = 2572)
Filter: (site_id = 1029)
-> Index Scan using goods_plan_daily_2022_10_06_pkey on goods_plan_daily_2022_10_06 (cost=0.28..2.50 rows=1 width=4) (actual time=0.005..0.005 rows=0 loops=1)
Index Cond: (id = 2572)
Filter: (site_id = 1029)
-> Index Scan using goods_plan_daily_2022_10_07_pkey on goods_plan_daily_2022_10_07 (cost=0.14..2.36 rows=1 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Index Cond: (id = 2572)
Filter: (site_id = 1029)
-> Index Scan using goods_plan_daily_2022_10_08_pkey on goods_plan_daily_2022_10_08 (cost=0.14..2.36 rows=1 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Index Cond: (id = 2572)
Filter: (site_id = 1029)
-> Bitmap Heap Scan on goods_plan_daily_2022_10_09 (cost=1.24..2.36 rows=1 width=4) (actual time=0.005..0.005 rows=0 loops=1)
Recheck Cond: (id = 2572)
Filter: (site_id = 1029)
-> Bitmap Index Scan on goods_plan_daily_2022_10_09_pkey (cost=0.00..1.24 rows=1 width=0) (actual time=0.003..0.003 rows=0 loops=1)
Index Cond: (id = 2572)
-> Index Scan using goods_plan_daily_2022_10_10_pkey on goods_plan_daily_2022_10_10 (cost=0.14..2.36 rows=1 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Index Cond: (id = 2572)
Filter: (site_id = 1029)
-> Index Scan using goods_plan_daily_2022_10_11_pkey on goods_plan_daily_2022_10_11 (cost=0.14..2.36 rows=1 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Index Cond: (id = 2572)
Filter: (site_id = 1029)
-> Index Scan using goods_plan_daily_2022_10_12_pkey on goods_plan_daily_2022_10_12 (cost=0.13..2.35 rows=1 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Index Cond: (id = 2572)
Filter: (site_id = 1029)
-> Index Scan using goods_plan_daily_2022_10_13_site_id_daily_idx on goods_plan_daily_2022_10_13 (cost=0.14..2.37 rows=1 width=4) (actual time=0.006..0.006 rows=0 loops=1)
Index Cond: (site_id = 1029)
Filter: (id = 2572)
Rows Removed by Filter: 2
-> Index Scan using goods_plan_daily_2022_10_14_site_id_daily_idx on goods_plan_daily_2022_10_14 (cost=0.14..2.37 rows=1 width=4) (actual time=0.005..0.005 rows=1 loops=1)
Index Cond: (site_id = 1029)
Filter: (id = 2572)
Rows Removed by Filter: 2
-> Index Scan using goods_plan_daily_2022_10_15_site_id_daily_idx on goods_plan_daily_2022_10_15 (cost=0.14..2.37 rows=1 width=4) (actual time=0.003..0.004 rows=0 loops=1)
Index Cond: (site_id = 1029)
Filter: (id = 2572)
-> Index Scan using goods_plan_daily_2022_10_16_site_id_daily_idx on goods_plan_daily_2022_10_16 (cost=0.14..2.37 rows=1 width=4) (actual time=0.002..0.002 rows=0 loops=1)
Index Cond: (site_id = 1029)
Filter: (id = 2572)
-> Index Scan using goods_plan_daily_2022_10_17_site_id_daily_idx on goods_plan_daily_2022_10_17 (cost=0.14..2.37 rows=1 width=4) (actual time=0.002..0.003 rows=0 loops=1)
Index Cond: (site_id = 1029)
Filter: (id = 2572)
-> Index Scan using goods_plan_daily_2022_10_18_site_id_daily_idx on goods_plan_daily_2022_10_18 (cost=0.14..2.37 rows=1 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Index Cond: (site_id = 1029)
Filter: (id = 2572)
-> Index Scan using goods_plan_daily_2022_10_19_site_id_daily_idx on goods_plan_daily_2022_10_19 (cost=0.14..2.37 rows=1 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Index Cond: (site_id = 1029)
Filter: (id = 2572)
-> Index Scan using goods_plan_daily_2022_10_20_site_id_daily_idx on goods_plan_daily_2022_10_20 (cost=0.14..2.37 rows=1 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Index Cond: (site_id = 1029)
Filter: (id = 2572)
-> Index Scan using goods_plan_daily_default_pkey on goods_plan_daily_default (cost=0.14..2.37 rows=1 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Index Cond: (id = 2572)
Filter: (site_id = 1029)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_01 (cost=0.00..317.44 rows=12595 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_02 (cost=0.00..332.91 rows=13193 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_03 (cost=0.00..350.73 rows=13898 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_04 (cost=0.00..840.56 rows=33645 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_05 (cost=0.00..16.86 rows=629 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_06 (cost=0.00..716.91 rows=28473 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_07 (cost=0.00..465.83 rows=18466 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_08 (cost=0.00..485.35 rows=19228 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_09 (cost=0.00..1199.76 rows=47581 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_10 (cost=0.00..1155.44 rows=44035 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_11 (cost=0.00..868.11 rows=29289 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_12 (cost=0.00..783.69 rows=31095 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_13 (cost=0.00..1198.16 rows=47533 width=8) (never executed)
Filter: (daily = $1)
-> Seq Scan on goods_plan_user_mapping_1029_2022_10_14 (cost=0.00..1172.26 rows=47381 width=8) (actual time=0.005..6.724 rows=47380 loops=1)
Filter: (daily = $1)
-> Bitmap Heap Scan on goods_plan_user_mapping_1029_2022_10_15 (cost=1.27..4.44 rows=3 width=8) (never executed)
Recheck Cond: (daily = $1)
-> Bitmap Index Scan on goods_plan_user_mapping_1029_2022_10_15_daily_idx (cost=0.00..1.27 rows=3 width=0) (never executed)
Index Cond: (daily = $1)
-> Bitmap Heap Scan on goods_plan_user_mapping_1029_2022_10_16 (cost=1.27..4.44 rows=3 width=8) (never executed)
Recheck Cond: (daily = $1)
-> Bitmap Index Scan on goods_plan_user_mapping_1029_2022_10_16_daily_idx (cost=0.00..1.27 rows=3 width=0) (never executed)
Index Cond: (daily = $1)
-> Bitmap Heap Scan on goods_plan_user_mapping_1029_2022_10_17 (cost=1.27..4.44 rows=3 width=8) (never executed)
Recheck Cond: (daily = $1)
-> Bitmap Index Scan on goods_plan_user_mapping_1029_2022_10_17_daily_idx (cost=0.00..1.27 rows=3 width=0) (never executed)
Index Cond: (daily = $1)
-> Bitmap Heap Scan on goods_plan_user_mapping_1029_2022_10_18 (cost=1.27..4.44 rows=3 width=8) (never executed)
Recheck Cond: (daily = $1)
-> Bitmap Index Scan on goods_plan_user_mapping_1029_2022_10_18_daily_idx (cost=0.00..1.27 rows=3 width=0) (never executed)
Index Cond: (daily = $1)
-> Bitmap Heap Scan on goods_plan_user_mapping_1029_2022_10_19 (cost=1.27..4.44 rows=3 width=8) (never executed)
Recheck Cond: (daily = $1)
-> Bitmap Index Scan on goods_plan_user_mapping_1029_2022_10_19_daily_idx (cost=0.00..1.27 rows=3 width=0) (never executed)
Index Cond: (daily = $1)
-> Bitmap Heap Scan on goods_plan_user_mapping_1029_2022_10_20 (cost=1.27..4.44 rows=3 width=8) (never executed)
Recheck Cond: (daily = $1)
-> Bitmap Index Scan on goods_plan_user_mapping_1029_2022_10_20_daily_idx (cost=0.00..1.27 rows=3 width=0) (never executed)
Index Cond: (daily = $1)
-> Index Scan using goods_plan_user_mapping_1029_default_daily_idx on goods_plan_user_mapping_1029_default (cost=0.42..248.46 rows=7482 width=8) (never executed)
Index Cond: (daily = $1)
Planning Time: 1.519 ms
Execution Time: 74.583 ms
```
# Postgresql Debug
## DB Lock
* 沒開獎
* 後台很卡
* Query要很久
1. 用Query平均時間、最久時間去分析有沒有Deadlock
```sql
select * from pg_stat_statements order by mean_time desc; --看平均值行時間
select * from pg_stat_statements order by max_time desc; -- 看最久時間
```
2. 看當下Lock的情況(查看多次,看有無Lock),或是等待什麼Lock
```sql
SELECT
COALESCE(blockingl.relation::regclass::text,blockingl.locktype) as locked_item,
blockeda.pid AS blocked_pid, blockeda.query as blocked_query,
blockedl.mode as blocked_mode, blockinga.pid AS blocking_pid,
blockinga.query as blocking_query, blockingl.mode as blocking_mode
FROM pg_catalog.pg_locks blockedl
JOIN pg_stat_activity blockeda ON blockedl.pid = blockeda.pid
JOIN pg_catalog.pg_locks blockingl ON(
( (blockingl.transactionid=blockedl.transactionid) OR
(blockingl.relation=blockedl.relation AND blockingl.locktype=blockedl.locktype)
) AND blockedl.pid != blockingl.pid)
JOIN pg_stat_activity blockinga ON blockingl.pid = blockinga.pid
WHERE NOT blockedl.granted;
```
3. 看執行時間大於5分鐘的Connection,或是等待什麼Lock
```sql
SELECT pid, now() - pg_stat_activity.query_start AS duration, query, state FROM pg_stat_activity WHERE now() - pg_stat_activity.query_start > interval '5 minutes';
```
4. 用以上的userid,去pg_user找是什麼使用者。
```sql
select * from pg_user;
```
5. 未來可以效能校調的部分
```sql
select * from pg_stat_statements pss where temp_blks_read > 0 order by mean_time desc;
```
## 補開獎、有效投注跟不上
1. 計劃未結算(當天),記得處理pyrite_bet_log
2. 計劃未結算非當天,要處理所有資料bet_log、lottery_bet_log、pyrite_bet_log、
statistic(總投注)、statistic_total(總投注)
## 資金明細錯誤或是入款方式錯
1. finance_log、deposit_withdraw_report、statistic_date_report、statistic