PostgreSQL使用建議(非常實用)
一、命名規範
1. DB object: database, schema, table, view, index, function, trigger等名稱
(1) 建議使用小寫字母、數字、下劃線的組合
(2) 建議不使用雙引號即"包圍,除非必須包含大寫字母或空格等特殊字元
(3) 長度不能超過63個字元
(4) 禁止使用 SQL 關鍵字,例如 type, order 等
2. table能包含的column數目,根據欄位型別的不同,數目在 250 到 1600 之間
3. 臨時或備份的DB object:table,view 等,建議加上日期,如table_xxx_20150826
4. index命名規則為
二、Column設計
1. 建議能用varchar(N) 就不用char(N),以利於節省儲存空間
2. 建議能用varchar(N) 就不用text,varchar
3. 建議使用default NULL,而不用default '',以節省儲存空間,
4. 建議使用ip4,ip4r,ip6,ip6r,ipaddress,iprange 來儲存
5. 建議使用timestamp with time zone(timestamptz),而不用timestamp without time zone,避免時間函式在對於不同時區的時間點返回值不同,也為業務國際化掃清障礙
6. 建議使用NUMERIC(precision, scale)來儲存貨幣金額和其它要求精確計算的數值, 而不建議使用real, double precision
7. 建議使用hstore 來儲存非結構化,key-value 鍵值型,對數不定的資料
8. 建議使用ltree
9. 建議使用json 來儲存JSON (JavaScript Object Notation) data
11. 建議使用如下range型別代替字串或多列來實現範圍的儲存
三、Constraints設計
1. 建議每個table都有主鍵;
2. 建議不要用有業務含義的名稱作為主鍵,比如身份證或者國家名稱,儘管其是unique的
3. 建議主鍵的一步到位的寫法:id serial primary key 或id bigserial primary key
四、Index設計
1. PostgreSQL 提供的index型別: B-tree, Hash, GiST (Generalized Search Tree), SP-GiST (space-partitioned GiST) and GIN (Generalized Inverted Index),目前不建議使用Hash, SP-GiST
2. 建議create 或 drop index 時,加 CONCURRENTLY引數,這是個好習慣,達到與寫入資料併發的效果
3. 建議對於頻繁update, delete的包含於index 定義中的column的table, 用create index CONCURRENTLY , drop index CONCURRENTLY 的方式進行維護其對應index
4. 建議用unique index 代替unique constraints,便於後續維護
5. 建議不要建過多index,一般不要超過6個,核心table(產品,訂單)可適當增加index個數
五、關於NULL
1. NULL 的判斷:IS NULL ,IS NOT NULL
2. 注意boolean 型別取值 true,false, NULL
3. 小心NOT IN 集合中帶有NULL元素
postgres=# SELECT * FROM (VALUES(1),(2)) v(a) ; a --- 1 2 (2 rows) postgres=# select 1 NOT IN (1, NULL); ?column? ---------- f (1 row) postgres=# select 2 NOT IN (1, NULL); ?column? ---------- (1 row) postgres=# SELECT * FROM (VALUES(1),(2)) v(a) WHERE a NOT IN (1, NULL); a --- (0 rows)
可見,出現這種情況的根本原因在於SELECT只返回WHERE中判斷條件結果為true的資料
4. 建議對字串型NULL值處理後,進行 || 操作
postgres=# select NULL||'PostgreSQL'; ?column? ---------- (1 row) postgres=# select coalesce(NULL,'')||'PostgreSQL'; ?column? ------------ PostgreSQL (1 row)
5. 建議對hstore 型別進行處理後,進行 || 操作,避免被NULL吃掉
postgres=# select NULL::hstore || ('key=>value') ; ?column? ---------- (1 row) postgres=# select coalesce(NULL::hstore, hstore(array[]::varchar[])) || ('key=>value') ; ?column? ---------------- "key"=>"value" (1 row) postgres=# select coalesce(NULL::hstore,''::hstore) || ('key=>value') ; ?column? ---------------- "key"=>"value" (1 row)
六、其他注意事項
1. 建議對DB object 尤其是COLUMN 加COMMENT,便於後續維護
2. 建議非必須時避免select *,只取所需欄位,以減少網路頻寬消耗,避免表結構變更對程式的影響
3. 建議update 時儘量做 <> 判斷,比如update table_a set column_b = c where column_b <> c
4. 建議將單個事務的多條SQL操作,分解、拆分,或者不放在一個事務裡,讓每個事務的粒度儘可能小,儘量lock少的資源,避免lock 、dead lock的產生
5. 建議向大size的table中add column時,將 alter table t add column col datatype not null default xxx;分解為如下,避免填充default值導致的過長時間鎖表
alter table t add column col datatype ; alter table t alter column col set default xxx; update t set column = default where id = 1; .................. update t set column = default where id = N; ------此處,可以用先進的\watch來刷------即 update table t set column= DEFAULT where id in ( select id from t where column is null limit 1000 ) ; \watch 3 alter table t alter column col set not null;
6. 建議執行DDL,比如CRAETE,DROP,ALTER 等, 不要顯式的開transaction, 因為加lock的mode非常高,極易產生deadlock
8. 建議發給PostgrSQL DBA review 及 執行的SQL,無論是使用pgadmin這種圖形化工具,還是pg_dump 這種命令列工具生成的SQL,都去掉註釋(--之後的部分),雙引號"及alter owner等冗餘或不應該帶到線上生產的dev/beta DB中的資訊