PostgreSQL以下簡寫為PG。PG在WIN下跑性能差是因?yàn)镻G在WIN下時(shí),實(shí)際是在一個(gè)UNIX的仿真器上運(yùn)行的,倒不是說WIN真的不行。目前用PG做應(yīng)用必須在UNIX類的系統(tǒng)上搞。至于具體用什么系統(tǒng),我個(gè)人覺得用LINUX簡單點(diǎn),因?yàn)镕REEBSD缺省時(shí)不支持SYSV的系統(tǒng)調(diào)用。所以安裝配置上就復(fù)雜了些。硬件嘛,我看不用什么IBM、SUN、HP或DEC一類的了,那不合使用PG的本意,如果你有錢買那些東西,也就不要用PG了,還是用ORACLE吧。同時(shí),如果你的數(shù)據(jù)庫規(guī)模不是太大(100G以內(nèi))也不一定非用64位的機(jī)器,不過SCSI硬盤是一定要的,能做RAID就更好了,一般為省點(diǎn)錢做個(gè)條帶效果比較明顯。
10年積累的網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì)經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站制作后付款的網(wǎng)站建設(shè)流程,更有道縣免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
一、PostgreSQL的穩(wěn)定性極強(qiáng),Innodb等引擎在崩潰、斷電之類的災(zāi)難場景下抗打擊能力有了長足進(jìn)步,然而很多MySQL用戶都遇到過Server級(jí)的數(shù)據(jù)庫丟失的場景——mysql系統(tǒng)庫是MyISAM的,相比之下,PG數(shù)據(jù)庫這方面要好一些。二、任何系統(tǒng)都有它的性能極限,在高并發(fā)讀寫,負(fù)載逼近極限下,PG的性能指標(biāo)仍可以維持雙曲線甚至對(duì)數(shù)曲線,到頂峰之后不再下降,而MySQL明顯出現(xiàn)一個(gè)波峰后下滑(5.5版本之后,在企業(yè)級(jí)版本中有個(gè)插件可以改善很多,不過需要付費(fèi))。
近些年對(duì)數(shù)據(jù)庫內(nèi)核的研究與開發(fā)多集中于存儲(chǔ)引擎層面,對(duì)查詢優(yōu)化器進(jìn)行深入分析的少之又少,更不用談與之相關(guān)的書籍,本書很好地彌補(bǔ)了這一空白。相信包括我在內(nèi)的很多數(shù)據(jù)庫開發(fā)人員都非常想知道數(shù)據(jù)庫查詢優(yōu)化器的底層實(shí)現(xiàn),本書不僅完成了對(duì)PostgreSQL查詢優(yōu)化器的分析,同時(shí)也完成了對(duì)MySQL查詢優(yōu)化器的分析,此外還對(duì)比了兩種數(shù)據(jù)庫的不同實(shí)現(xiàn),內(nèi)容夯實(shí)有力,相信對(duì)從事數(shù)據(jù)庫相關(guān)工作的人員來說會(huì)有極大的幫助。
1。打開psql界面,輸入以下:
SELECT pg_stat_get_backend_pid(s.backendid) AS procpid,
pg_stat_get_backend_activity(s.backendid) AS current_query
FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;
2。同時(shí)監(jiān)視你的數(shù)據(jù)庫服務(wù)器什么時(shí)候發(fā)生update waitting狀況,一旦發(fā)現(xiàn),立刻記錄下它的進(jìn)程號(hào)。
3。迅速把第1步里的語句按回車執(zhí)行了,查看結(jié)果。結(jié)果是一個(gè)view,結(jié)構(gòu)大致如下:
procpid | current_query
---------+-------------------------------------------------------------------
26574 | IDLE
26640 | IDLE
26643 | IDLE
26651 | IDLE
26646 | IDLE
26649 | IDLE
26654 | IDLE
26657 | IDLE in transaction
26659 | IDLE
26674 | IDLE
23623 | IDLE
26824 | SELECT pg_stat_get_backend_pid(s.backendid) AS procpid,
: pg_stat_get_backend_activity(s.backendid) AS current_query
: FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;
26901 | IDLE
(這是我目前開發(fā)機(jī)器上的結(jié)果,沒有正在執(zhí)行的語句,如果有,IDLE就會(huì)是SQL語句,最下面的哪條是這個(gè)性能執(zhí)行查詢自身的語句)
你把左側(cè)一列的procpid號(hào)對(duì)應(yīng)上在第2步中查到的進(jìn)程號(hào),然后把對(duì)應(yīng)上的current_query 發(fā)出來,讓大家?guī)湍憧纯词悄木鋟pdate語句執(zhí)行了過長的時(shí)間,針對(duì)這條update語句再查原因可能會(huì)準(zhǔn)確些。
一、使用EXPLAIN:
PostgreSQL為每個(gè)查詢都生成一個(gè)查詢規(guī)劃,因?yàn)檫x擇正確的查詢路徑對(duì)性能的影響是極為關(guān)鍵的。PostgreSQL本身已經(jīng)包含了一個(gè)規(guī)劃器用于尋找最優(yōu)規(guī)劃,我們可以通過使用EXPLAIN命令來查看規(guī)劃器為每個(gè)查詢生成的查詢規(guī)劃。
PostgreSQL中生成的查詢規(guī)劃是由1到n個(gè)規(guī)劃節(jié)點(diǎn)構(gòu)成的規(guī)劃樹,其中最底層的節(jié)點(diǎn)為表掃描節(jié)點(diǎn),用于從數(shù)據(jù)表中返回檢索出的數(shù)據(jù)行。然而,不同
的掃描節(jié)點(diǎn)類型代表著不同的表訪問模式,如:順序掃描、索引掃描,以及位圖索引掃描等。如果查詢?nèi)匀恍枰B接、聚集、排序,或者是對(duì)原始行的其它操作,那
么就會(huì)在掃描節(jié)點(diǎn)"之上"有其它額外的節(jié)點(diǎn)。并且這些操作通常都有多種方法,因此在這些位置也有可能出現(xiàn)不同的節(jié)點(diǎn)類型。EXPLAIN將為規(guī)劃樹中的每
個(gè)節(jié)點(diǎn)都輸出一行信息,顯示基本的節(jié)點(diǎn)類型和規(guī)劃器為執(zhí)行這個(gè)規(guī)劃節(jié)點(diǎn)計(jì)算出的預(yù)計(jì)開銷值。第一行(最上層的節(jié)點(diǎn))是對(duì)該規(guī)劃的總執(zhí)行開銷的預(yù)計(jì),這個(gè)數(shù)
值就是規(guī)劃器試圖最小化的數(shù)值。
這里有一個(gè)簡單的例子,如下:
復(fù)制代碼 代碼如下:
EXPLAIN SELECT * FROM tenk1;
QUERY PLAN
-------------------------------------------------------------
Seq Scan on tenk1 (cost=0.00..458.00 rows=10000 width=244)
EXPLAIN引用的數(shù)據(jù)是:
1). 預(yù)計(jì)的啟動(dòng)開銷(在輸出掃描開始之前消耗的時(shí)間,比如在一個(gè)排序節(jié)點(diǎn)里做排續(xù)的時(shí)間)。
2). 預(yù)計(jì)的總開銷。
3). 預(yù)計(jì)的該規(guī)劃節(jié)點(diǎn)輸出的行數(shù)。
4). 預(yù)計(jì)的該規(guī)劃節(jié)點(diǎn)的行平均寬度(單位:字節(jié))。
這里開銷(cost)的計(jì)算單位是磁盤頁面的存取數(shù)量,如1.0將表示一次順序的磁盤頁面讀取。其中上層節(jié)點(diǎn)的開銷將包括其所有子節(jié)點(diǎn)的開銷。這里的輸出
行數(shù)(rows)并不是規(guī)劃節(jié)點(diǎn)處理/掃描的行數(shù),通常會(huì)更少一些。一般而言,頂層的行預(yù)計(jì)數(shù)量會(huì)更接近于查詢實(shí)際返回的行數(shù)。
現(xiàn)在我們執(zhí)行下面基于系統(tǒng)表的查詢:
復(fù)制代碼 代碼如下:
SELECT relpages, reltuples FROM pg_class WHERE relname = 'tenk1';
從查詢結(jié)果中可以看出tenk1表占有358個(gè)磁盤頁面和10000條記錄,然而為了計(jì)算cost的值,我們?nèi)匀恍枰懒硗庖粋€(gè)系統(tǒng)參數(shù)值。
復(fù)制代碼 代碼如下:
postgres=# show cpu_tuple_cost;
cpu_tuple_cost
----------------
0.01
(1 row)
cost = 358(磁盤頁面數(shù)) + 10000(行數(shù)) * 0.01(cpu_tuple_cost系統(tǒng)參數(shù)值)
下面我們?cè)賮砜匆粋€(gè)帶有WHERE條件的查詢規(guī)劃。
復(fù)制代碼 代碼如下:
EXPLAIN SELECT * FROM tenk1 WHERE unique1 7000;
QUERY PLAN
------------------------------------------------------------
Seq Scan on tenk1 (cost=0.00..483.00 rows=7033 width=244)
Filter: (unique1 7000)
EXPLAIN的輸出顯示,WHERE子句被當(dāng)作一個(gè)"filter"應(yīng)用,這表示該規(guī)劃節(jié)點(diǎn)將掃描表中的每一行數(shù)據(jù),之后再判定它們是否符合過濾的條
件,最后僅輸出通過過濾條件的行數(shù)。這里由于WHERE子句的存在,預(yù)計(jì)的輸出行數(shù)減少了。即便如此,掃描仍將訪問所有10000行數(shù)據(jù),因此開銷并沒有
真正降低,實(shí)際上它還增加了一些因數(shù)據(jù)過濾而產(chǎn)生的額外CPU開銷。
上面的數(shù)據(jù)只是一個(gè)預(yù)計(jì)數(shù)字,即使是在每次執(zhí)行ANALYZE命令之后也會(huì)隨之改變,因?yàn)锳NALYZE生成的統(tǒng)計(jì)數(shù)據(jù)是通過從該表中隨機(jī)抽取的樣本計(jì)算的。
如果我們將上面查詢的條件設(shè)置的更為嚴(yán)格一些的話,將會(huì)得到不同的查詢規(guī)劃,如:
復(fù)制代碼 代碼如下:
EXPLAIN SELECT * FROM tenk1 WHERE unique1 100;
QUERY PLAN