postgreSql入門相關&理解

文章沒涉及太底層的原理,個人把覺得欠缺的和重要的以及發現的一些新鮮用法記錄在這篇博客。

標題四和標題五爲文章重點,不分先後。文章涉及索引的例子我創建了三百萬條數據真實測試才寫的。

一!安裝

Linux如何安裝PG可以參考網上搜的這篇文章:https://blog.csdn.net/zhu_xun/article/details/21234663

或者官網這篇:http://www.postgres.cn/docs/9.6/installation.html

就是安裝時要是報沒有readline   ubuntu 執行 apt-get install libreadline6-dev 就行了。 我安裝的是9.6版本的PG

安裝就不多寫了。   .configure安裝是可以指定參數安裝一些額外的東西的。

二!概念性筆記

在數據庫術語裏,PostgreSQL使用一種客戶端/服務器的模型。一次PostgreSQL會話由下列相關的進程(程序)組成:

  • 一個服務器進程,它管理數據庫文件、接受來自客戶端應用與數據庫的聯接並且代表客戶端在數據庫上執行操作。 該數據庫服務器程序叫做postgres。

  • 那些需要執行數據庫操作的用戶的客戶端(前端)應用。 客戶端應用可能本身就是多種多樣的:可以是一個面向文本的工具, 也可以是一個圖形界面的應用,或者是一個通過訪問數據庫來顯示網頁的網頁服務器,或者是一個特製的數據庫管理工具。 一些客戶端應用是和 PostgreSQL發佈一起提供的,但絕大部分是用戶開發的。

下面是我pg起來的進程。目前沒啥連接。因爲我根本沒有用它。。。

來切換postgresql這個操作系統用戶來進行創建數據庫試試。因爲我們安裝時 useradd 的是 postgresql  所以數據庫默認用戶就是它了。

su - postgresql                               createdb testdb                            dropdb   testdb  就刪庫跑路了。

然後用psql命令進數據庫裏面去。就可以寫SQL了。

\h    #查看所有的sql關鍵字
\?     #命令行操作的幫助
\d     #查看當前schema 中所有的表
\q    #退出pg命令行
\d    #schema.table 查看錶的結構
\x    #橫縱顯示切換 
\dT+    #顯示擴展類型相關屬性及描述
\dx    #顯示已安裝的擴展插件
\l    #列出所有的數據庫
\! hostname    #列出當前的主機名
\timing    #顯示執行時間
\c database_name    #切換數據庫

三!然後數據庫SQL語句跟MySQL賊像,crud如出一轍。

建表用可視化工具就好了,賊方便。比如Navicat

select  *  from test;

delete from test;

insert into test(name,sex) values('test',0);

update test set name = 'zy';

還有這個copy命令。從文件導入到表和導出到文件(例如csv文件) COPY tableName  FROM '/home/user/name.txt';

COPY table_name [ ( column_name [, ...] ) ]
    FROM { 'filename' | PROGRAM 'command' | STDIN }
    [ [ WITH ] ( option [, ...] ) ]

COPY { table_name [ ( column_name [, ...] ) ] | ( query ) }
    TO { 'filename' | PROGRAM 'command' | STDOUT }
    [ [ WITH ] ( option [, ...] ) ]

測試一下。纔有說服力。別忘了把權限chown給postgresql   然後給文件讀寫權限。

copy (SELECT * FROM "user") to '/test.csv' (format csv, delimiter ';');

copy user from '/test.csv' (format csv, delimiter ';');  把數據從文件複製回去。這裏我將表裏數據先刪除再測試的。

copy tb_user from '/user.csv' (format csv, delimiter ';');  --user 這個表名不太行,我就換了個名,然後就好使了。數據也是存在的。我就不貼出來了。據說這個做大批量轉儲賊好用。

還有批量插入的方法。配合on  conflict

insert  into testTable (a,b)  select  a,b from testTable2  on  conflict  do nothing;  這個覺得很好用。正常插入肯定是要查存不存在的,存在就更新,不存在就插入。這個  on  conflict 就是這麼玩的。  (上面這個SQL按需求寫就行了。)

然後接下來就是連接了。其實跟MySQL也差不多。。。

from A left  outer  join B  on a.bid = b.id     相似的還有   right  outer  join  |   full  outer  join  | inner  join

然後其他的SQL語法跟MySQL差不多。就不贅述了。還有聚集函數,分組,子查詢,having等等。

四!PG的一些SQL寫法

1. 內連接  也可以不寫inner 直接寫join
inner 內連接  取交集
SELECT table1.columns, table2.columns  
FROM table1  
INNER JOIN table2  
ON table1.common_filed = table2.common_field

2.左外連接
left outer join 左外連接  返回左表所有行,並附帶右表滿足條件的行。
SELECT table1.columns, table2.columns  
FROM table1  
LEFT OUTER JOIN table2  
ON table1.common_filed = table2.common_field;

3.右外連接
right outer join 右外連接
SELECT table1.columns, table2.columns  
FROM table1  
RIGHT OUTER JOIN table2  
ON table1.common_filed = table2.common_field;

4.取並集
full outer join 取並集。另外表沒有的列就顯示空。不去除。
SELECT table1.columns, table2.columns  
FROM table1  
FULL OUTER JOIN table2  
ON table1.common_filed = table2.common_field;

5.銷燬表數據
truncate table test;  這種清空的方式也不會重置自增序列,但是可以加參數。

delete from test;   刪除數據分爲這兩種、delete不會重置自增序列。

PostgreSQL 中 TRUNCATE TABLE 用於刪除表的數據,但不刪除表結構。
也可以用 DROP TABLE 刪除表,但是這個命令會連表的結構一起刪除,如果想插入數據,需要重新建立這張表。
TRUNCATE TABLE 與 DELETE 具有相同的效果,但是由於它實際上並不掃描表,所以速度更快。 此外,TRUNCATE TABLE 可以立即釋放表空間,而不需要後續 VACUUM 操作,這在大型表上非常有用。
PostgreSQL VACUUM 操作用於釋放、再利用更新/刪除行所佔據的磁盤空間。

6.創建自增ID
CREATE SEQUENCE upms_log_id_seq START 1;  設計表時直接選serial就是自增了,會自動執行這個sql 

PG中設置自增ID   選擇的類型爲 serial  不選這個serial 就默認值設置爲 nextval('upms_log_id_seq')

7.修改自增起始
alter sequence upms_log_id_seq restart with 1

8.添加/刪除表的唯一性約束
ALTER TABLE table_name
ADD CONSTRAINT uniqueDouble UNIQUE(col1,col2);  //聯合唯一索引
唯一約束的話實際上創建了唯一索引,這樣做插入操作時想要去重,使用唯一約束的效率會提高很多。

ALTER TABLE table_name DROP COLUMN col1;  

ALTER TABLE table_name ADD CHECK (name = ''); 檢查性約束。

ALTER TABLE table_name DROP CONSTRAINT constraint_name;

9. 查索引大小
查指定索引的大小。
select pg_size_pretty(pg_relation_size('test_idx'));

10. show 配置項
show work_mem  等等 查看數據庫配置  postgresql.conf 文件中配置。
select * from pg_stat_activity  查連接的詳細信息。可以服務器診斷

11. 獲取所有的函數信息
SELECT
  pg_proc.proname AS functionName,
  pg_type.typname AS voidType,
  pg_proc.pronargs AS paramNum
FROM  pg_proc  JOIN pg_type
ON (pg_proc.prorettype = pg_type.oid)
WHERE  pronamespace = (SELECT pg_namespace.oid FROM pg_namespace WHERE nspname = 'public')

12. 做數據插入時使用默認值

 INSERT INTO products (num, name, salary) VALUES (1, 'Cheese', DEFAULT); //插入時指定插入默認值。

13. 強制類型轉換。cast();函數

select CAST('123' as FLOAT)/3;    --41      cast(expr as type)

14. 查數據庫下所有模式以及所有表。
select * from pg_tables

15. 查看當前數據庫所有觸發器
SELECT * FROM pg_trigger

16. numeric值的計算在可能的情況下會得到準確的結果。
例如加法、減法、乘法。不過,numeric類型上的算術運算比整數類型或者下一節描述的浮點數類型要慢很多。
對於numeric來說指定比例在移植性看來不錯,但是不指定比較靈活。就像varchar

17. 除了普通的數字值之外,浮點類型還有幾個特殊值:
Infinity     正無窮
-Infinity    負無窮
NaN          不是一個數字

18.序數類型 serial 不是真正的數據類型,是創建唯一標識符而存在的符號。
CREATE TABLE tablename (
    colname SERIAL
);
等價於
CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
序數是用序列實現的,所以即使沒插入成功也會自增,而手動指定id,並不會使序列自增。

19. PG也有枚舉類型。
CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy'); 定義完枚舉類型,建表的時候是可以使用的。CREATE TABLE

20. PG數組類型的玩法
"ids" integer[],
insert into salary_test(name,num,salary,zy_date,ids) values('zy',100,100000,date '2019-10-07','{1,2,3}');

select ids[1] from salary_test 取對應索引下標,奇怪的是下標1爲起始。
相應的更新操作也是這麼玩的。也可以指定更新 UPDATE salary_test set ids[2] = 100  

21. exists
EXISTS的參數是一個任意的SELECT語句, 或者說子查詢。系統對子查詢進行運算以判斷它是否返回行。如果它至少返回一行,那麼EXISTS的結果就爲"真"; 如果子查詢沒有返回行,那麼EXISTS的結果是"假"。

22. COALESCE
COALESCE()匹配第一個不爲null的值,備選值必須與列的類型一樣。

select COALESCE(salary,-1,0) from salary_table where id = 8 

23. 關於日期。

使用比較多的是時間戳 timestamp (默認沒時區) 和 date 

24. case when end
SELECT salary, num, 
CASE WHEN num < 10 AND num > 4 
THEN 1 WHEN num > 10 THEN 2 ELSE 3 
END 
FROM salary_table

25. 可以寫子查詢的表達式
exists ()  in () not in () any () some () all ()

26. 造假數據generate_series(11,20,step)生成數。
insert into tb_user select generate_series(11,20),'zy'||random(),1,'hobby test';  --生成多行記錄

27. 所有系統函數(錨點是指向了系統目錄信息函數與庫表索引相關)
http://www.postgres.cn/docs/9.6/functions-info.html#FUNCTIONS-INFO-CATALOG-TABLE

28. 系統管理函數(錨點指向鎖)
http://www.postgres.cn/docs/9.6/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS-TABLE

29. 對於索引來說。

PG一共有六種類型的索引,經比較直接創建B-tree就好了。其餘類型的索引使用場景較少。DDL默認使用的就是B-tree

30.當前只有B-tree能聲明唯一索引。
不需要手工在唯一列上創建索引,如果那樣做也只是重複了自動創建的索引而已。

31.刪庫
如果庫被佔用刪不了的。查出佔用的進程,然後kill -9 掉進程,就可以dropdb testdb了。

32.查看所有鎖。
select* from pg_locks 

33.查看錶的磁盤使用
SELECT pg_relation_filepath(oid), relpages FROM pg_class WHERE relname = 'tablename';
每個頁通常都是 8K 字節

34.按年月截取數據庫中的數據

date_trunc ('month', zy_date) as zy_month 此時可以用他來分組。  對於一些  按day存儲的數據想按月統計很方便。

35.結果集聚合成字符串,並以一個分隔符連接。

string_agg ( zy_NAME || '', '/' ) AS zy_name_res      用/來分割。
 

五!PG一些比較常用的用法

1.上面說過的copy算是一個特性。就不說了。

2. 窗口函數之排名 rank + over 

對於下面這個數據,我想取每個人工資第二高的,試想不使用函數算第一名容易,算這個第二名還是挺麻煩的。使用over和rank函數來計算就很方便了。

select id, name, salary,rank() over(PARTITION by name ORDER BY salary desc nulls last) FROM salary_table;

如上這個rank() over() 函數,其中over 中的partition by col 可以理解爲通過某列分組,後面的排序就是按自己想要的排序就行,如上是按薪水降序。將null值放到最後。拿到這個結果集再取排名第幾的就很方便了。(窗口函數在select中,注意執行順序)

還可以使用window 來定義窗口函數,這樣能複用了。

3. null與null是不一樣的。即便你對某個字段加了唯一約束或者唯一索引,執行數據插入時對這個字段插入非null是可以保證限制的。一旦每次插入的都是null時,唯一限制起不到作用。因爲每次插入的null是不一樣的。

4. 分表、

CREATE TABLE son_12(CHECK ( in_date >= DATE '2019-12-01' AND in_date <= DATE '2019-12-31' )) INHERITS (parent);

建parent的分表。

父表上的所有檢查約束和非空約束都將自動被它的後代所繼承。其他類型的約束(唯一、主鍵和外鍵約束)則不會被繼承。

被子表繼承的東西,不能在子表刪,子表存在父表不能刪。(cascade能刪,但是比較危險,鬼知道你都哪裏用了)

salary_table是父表名。salart_02是子表名。

DROP TABLE salart_02;   刪表。清除舊數據用的。
ALTER TABLE salart_02 NO INHERIT salary_table;  消除子表與父表的分區關係。

在數據量非常大的情況下,做按月分表就可以用以上這種方式。製造check檢查性約束。(檢查性約束會繼承,因此每個表要創建按日期不同的檢查性約束。)開啓約束排除後,按照檢查性約束where時指定篩選的日期就能去掉不在where中的分區,從而減少查詢基數) 分區控制在一百以內。

對於分表時設置每個分表的check
((zy_date >= '2019-09-01'::date) AND (zy_date < '2019-10-01'::date))
注意:需要每個分表都設置這個不同日期的check 並且開啓SET constraint_exclusion = on/partition; 否則不生效的。我測試了off是不生效的。

分表時父表的索引,約束可以被拷貝到子表。(如下命令父表中的索引與唯一約束會被拷貝到04子表。)
CREATE TABLE salary_04 (like salary_table including indexes) INHERITS (salary_table);

創建表時繼承使用inherits關鍵字,而已有的表繼承其他表使用inherit關鍵字。

5.父子表的關係

向子表插入的數據是在父表可以直接顯示出來的,在子表/父表刪除這個數據,都會使數據在兩張表都不顯示。
不是將數據又插入到了父表,而是通過繼承關係使子表的數據在父表可見。

only關鍵字,在查詢時加上,會只查對應表。如果數據真實在子表中,父表就查不出來了。

insert into salary_04(name,salary,num,zy_date) values('zzzy',10000,1,date '2019-05-20');

select * from only salary_table where name = 'zzzy'   ----null 不加only可以查出來、
select * from salary_table where name = 'zzzy'

注:相應的drop掉子表後,salary_table 父表中記錄也被幹掉了。drop table salary_05;

對於插入父表。不設置觸發器等操作不會插入到那個子表。而插入子表的數據一定會在父表中顯示。
查詢查父表指定check的日期檢索就可以快速查找,插入直接插入對應的子表中就行了。因爲命名一般都是按日期命名的。代碼裏完全可以動態。

6. SQL執行順序

大方向 from >where > group by > having > select  > distinct > order by > limit

7. UNION

這個也有用到。UNION 與 UNION ALL 的區別是前者去重,後者不去重。如果肯定沒有重複的話使用後者會快一些。

這個是不保證順序的。去重是按照結果集select出來的列聯合去重的。

select name from salary_02 union SELECT name from salary_table ORDER BY name

8. 聚集函數 sum中使用  sum(case name = 'a' then salary else 0 end) 用來統計每個分組下的薪資總和。沒有數據返回0

9.對於判斷數據庫中某一行是否存在(where條件會限定結果集只有一行)
使用select 1 來代替select col 或 select * 
select 1  1是常量不會查詢字典表,所以效率要高於*與col

10.distinct 去重
在insert數據時,每次insert進入的null是不一樣的。但是distinct去重中的null是相同的。

11.limit  offset 分頁時offset越往後越慢。分頁時要保證做一個排序。

12. WITH 查詢

WITH sel1 as (
    select * from salary_table
), sel2 as (
    select * from sel1 where name = 'a'
)
select * from sel2 where num > 1;

這個就是牛逼版的子查詢,可以複用。上面這個例子舉得不好,但是語法表達了。這個不需要 ;在最最後加分號就行

13. WITH RECURSIVE 遞歸

這個遞歸還是很好用的。先展示一下表數據。下面這個樹給你某個pid讓你找所有下級或者所有上級、以pid爲2爲例。遞歸找所有pid爲2的子節點。

                結果集=>               

WITH RECURSIVE sel1 as (
    select * from recursion where pid in (2)
    union all
    select son.* from sel1 as parent inner join recursion as son on son.pid = parent.id 
)
select * from sel1;

下面是向上遞歸

WITH RECURSIVE sel1 as (
    select * from recursion where id =4
    union all
    select son.* from sel1 as parent 
    inner join recursion as son 
    on parent.pid = son.id

)
select * from sel1;

解釋:上面這個SQL---select * from recursion where id =4 最先被執行,結果塞入sel1中然後union all 遞歸斜體部分。

14. with 中寫非查詢語句
with sel1 as(
 delete  from salary_table where id>10
 returning *
)
insert into salary_01
SELECT * from sel1;

如下sql結果num=107 但是主查詢sel1變成salary_table就查詢到的是改動之前的值了。
with sel1 as(
 update salary_table set num = 107 where id = 1
 returning *
)
SELECT * from sel1 where id= 1;

如下sql結果num=107 但是主查詢sel1變成salary_table就查詢到的是改動之前的值了。
with sel1 as(
 update salary_table set num = 107 where id = 1
 returning *
)
SELECT * from sel1 where id= 1;

15.去重性能比對
select count(distinct col1,col2)
distinct 去重會將去重列全部內容存儲在內存hash結構中,hash的key爲col,  最後取key就可以了。
select count(1) from xx group by col1,col2;
而group by的方式是先將col排序。而數據庫中的group一般使用sort的方法,即數據庫會先對col進行排序。而排序的基本理論是,時間複雜爲nlogn,空間爲1,
然後只要單純的計數就可以了。優點是空間複雜度小,缺點是要進行一次排序,執行時間會較長。

16.組合索引 (name,sex) name='zy' and sex= 1 可以觸發索引,or不可以觸發。

EXPLAIN ANALYZE select * from tb_user where name = 'zy1' or name = 'zy0'; 這種是可以觸發索引的,觸發了兩次。將or兩端的查詢給拆開了。這麼看上述的or沒觸發索引也解釋通了。因爲sex不能直接被索引。(聯合索引的特性)

而就在我給sex又單獨創建一個索引後,or兩邊的name和sex都成功走索引了。
有時候多列索引最好,但是有時更好的選擇是創建單獨的索引並依賴於索引組合特性。

17.可以創建表達式索引,表達式索引是對錶達式的索引,因此使用場景並不是很多。
SELECT * FROM test1 WHERE lower(col1) = 'value';
CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));

18.部分索引。

指的是對某一列或者某些列的一定範圍創建索引,只有where查詢在這個範圍才能用得上這個索引。沒感覺咋好用。
CREATE INDEX zy_client_ip_ix ON testTable (client_ip)
WHERE NOT (client_ip > inet '192.168.100.0');

19.like&&ilike
匹配方式有_ % 兩種。單個未知和多個未知、
like是區分大小寫的。 like 'huawei%' 如果是 huaWei就不會被匹配到。
ilike是不區分大小寫的。  ilike 'huawei%' 會匹配到 huaWEI 
like還可以複製表結構。上面那個父子表中就是使用like這個特性了。

20.user表

PG 有一個系統表叫user。  創建表爲user後,查詢我們自己創建的user 需要  public.user 指定,否則默認是系統表的user.

21.填充一個數據庫
(1)可以取消事務的自動提交併將多個insert放到一個事務中,會提高插入效率。 
如果一個行的插入失敗則所有值錢插入的行都會被回滾,這樣你不會被卡在部分載入的數據中。
使用copy來填充文件內容到數據庫是最快的。 插入時移除索引,插入完畢再加索引。(約束索引別這麼玩) 

(2)增加maintenance_work_mem 增大這個參數,創建索引和外鍵會很快速。創建完再改回來。

(3)臨時增大max_wal_size 
這是因爲向PostgreSQL中載入大量的數據將導致檢查點的發生比平常(由checkpoint_timeout配置變量指定)更頻繁。無論何時發生一個檢查點時,所有髒頁都必須被刷寫到磁盤上。 通過在批量數據載入時臨時增加max_wal_size,所需的檢查點數目可以被縮減。

(4)禁用WAL歸檔和流複製
當使用WAL歸檔或流複製向一個安裝中載入大量數據時,在錄入結束後執行一次新的基礎備份比處理大量的增量 WAL 數據更快。爲了防止載入時記錄增量 WAL,通過將wal_level設置爲minimal、將archive_mode設置爲off以及將max_wal_senders設置爲零來禁用歸檔和流複製。 但需要注意的是,修改這些設置需要重啓服務。

22.數據更新較多可以時常重建索引,減少缺頁分頁。
對於B樹索引,一個新建立的索引比更新了多次的索引訪問起來要略快, 因爲在新建立的索引上,邏輯上相鄰的頁面通常物理上也相鄰(這樣的考慮目前並不適用於非B樹索引)。僅僅爲了提高訪問速度也值得定期重索引。

23.對於索引列設置

設置索引列爲not null  並且給一個默認值。在創建索引的時候給順序和null的排名last還是first。

因爲給索引列加了排序,索引對於索引列的order by   group by  distinct操作都是可以走索引來加快速度的。

(ps:時間多可能是我在租的服務器部署的PG,網絡帶寬和IO的因素。)

六!進階的知識點

1.關於事務隔離級別以及髒讀,不可重複讀,幻讀

事務的隔離級別分爲1.讀未提交,2.讀已提交,3.可重複讀,4.序列化
1會導致髒讀,會導致數據庫數據錯亂,是不被允許的。
2會導致不可重複讀,就是同一個事務兩次讀取的數據是不一致的,在數據的層面。update觸發  行數--結果集是不變的。
如果整個事務讀和修改是分開的,那麼就不存在這個問題了。 
3會導致幻讀,也是同一個事務兩次讀取的數據是不一致的,是在數據結果集的層面。insert delete觸發  併發事務在update修改相同行,本事務就會回滾。
幻讀和不可重複讀影響差不多。數據都是異常的。    而數據庫中數據是正常的,讀出來的數據異常。
4序列化因爲讀出記錄不對也是會事務回滾,所以不會出現上述問題。

2.PG的一些重要的系統參數

(0)設置max_worker_processes 設置系統能夠支持的後臺進程的最大數量。這個參數只能在服務器啓動時設置。 默認值爲 8。

(1)shared_buffers:這是最重要的參數,postgresql通過shared_buffers和內核和磁盤打交道,因此應該儘量大,讓更多的數據緩存在shared_buffers中。
一個合理的shared_buffers開始值是系統內存的 25%。
爲了能把對寫大量新的或改變的數據的處理分佈在一個較長的時間段內, shared_buffers更大的 設置通常要求對max_wal_size也做相應增加。

(2)work_mem: postgresql在執行排序操作時,會根據work_mem的大小決定是否將一個大的結果集拆分爲幾個小的和 work_mem查不多大小的臨時文件。顯然拆分的結果是降低了排序的速度。因此增加work_mem有助於提高排序的速度。通常設置爲實際RAM的2% -4%,根據需要排序結果集的大小而定,比如81920(80M)
指定在寫到臨時磁盤文件之前被內部排序操作和哈希表使用的內存量。該值默認爲四兆字節(4MB)。注意對於一個複雜查詢, 可能會並行運行好幾個排序或者哈希操作;每個操作都會被允許使用這個參數指定的內存量,然後纔會開始寫數據到臨時文件。同樣,幾個正在運行的會話可能併發進行這樣的操作。
因此被使用的總內存可能是work_mem值的好幾倍,在選擇這個值時一定要記住這一點。
ORDER BY、DISTINCT和歸併連接都要用到排序操作。哈希連接、基於哈希的聚集以及基於哈希的IN子查詢處理中都要用到哈希表。

(3)effective_cache_size:是postgresql能夠使用的最大緩存,這個數字對於獨立的pgsql服務器而言應該足夠大,比如4G的內存,可以設置爲3.5G(437500)

(4)maintence_work_mem:
指定在維護性操作(例如VACUUM、CREATE INDEX和ALTER TABLE ADD FOREIGN KEY)中使用的 最大的內存量。其默認值是 64 兆字節(64MB)。因爲在一個數據庫會話中,一個時刻只有一個這樣的操作可以被執行,並且一個數據庫安裝通常不會有太多這樣的操作併發執行, 把這個數值設置得比work_mem大很多是安全的。 更大的設置可以改進清理和恢復數據庫轉儲的性能。

注意當自動清理運行時,可能會分配最高達這個內存的 autovacuum_max_workers倍, 因此要小心不要把該默認值設置得太高。 通過獨立地設置autovacuum_work_mem 可能會對控制這種情況有所幫助。

(5)max_connections: 通常,max_connections的目的是防止max_connections * work_mem超出了實際內存大小。比如,如果將work_mem設置爲實際內存的2%大小,則在極端情況下,如果有50個查詢都有排序要求,而且都使 用2%的內存,則會導致swap的產生,系統性能就會大大降低。當然,如果有4G的內存,同時出現50個如此大的查詢的機率應該是很小的。不過,要清楚 max_connections和work_mem的關係。

 

最後一點:學PG可以使用explain   並時常 explain  analyze  select  通過分析進行SQL優化、

 

參考PG中文文檔:http://www.postgres.cn/docs/9.6/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章