| 特性 | MySQL | PostgreSQL |
| 實(shí)例 | 通過執(zhí)行 MySQL 命令(mysqld)啟動(dòng)實(shí)例。一個(gè)實(shí)例可以管理一個(gè)或多個(gè)數(shù)據(jù)庫(kù)。一臺(tái)服務(wù)器可以運(yùn)行多個(gè) mysqld 實(shí)例。一個(gè)實(shí)例管理器可以監(jiān)視 mysqld 的各個(gè)實(shí)例。 | 通過執(zhí)行 Postmaster 進(jìn)程(pg_ctl)啟動(dòng)實(shí)例。一個(gè)實(shí)例可以管理一個(gè)或多個(gè)數(shù)據(jù)庫(kù),這些數(shù)據(jù)庫(kù)組成一個(gè)集群。集群是磁盤上的一個(gè)區(qū)域,這個(gè)區(qū)域在安裝時(shí)初始化并由一個(gè)目錄組成,所有數(shù)據(jù)都存儲(chǔ)在這個(gè)目錄中。使用 initdb 創(chuàng)建第一個(gè)數(shù)據(jù)庫(kù)。一臺(tái)機(jī)器上可以啟動(dòng)多個(gè)實(shí)例。 |
| 數(shù)據(jù)庫(kù) | 數(shù)據(jù)庫(kù)是命名的對(duì)象集合,是與實(shí)例中的其他數(shù)據(jù)庫(kù)分離的實(shí)體。一個(gè) MySQL 實(shí)例中的所有數(shù)據(jù)庫(kù)共享同一個(gè)系統(tǒng)編目。 | 數(shù)據(jù)庫(kù)是命名的對(duì)象集合,每個(gè)數(shù)據(jù)庫(kù)是與其他數(shù)據(jù)庫(kù)分離的實(shí)體。每個(gè)數(shù)據(jù)庫(kù)有自己的系統(tǒng)編目,但是所有數(shù)據(jù)庫(kù)共享 pg_databases。 |
| 數(shù)據(jù)緩沖區(qū) | 通過innodb_buffer_pool_size配置參數(shù)設(shè)置數(shù)據(jù)緩沖區(qū)。這個(gè)參數(shù)是內(nèi)存緩沖區(qū)的字節(jié)數(shù),InnoDB 使用這個(gè)緩沖區(qū)來緩存表的數(shù)據(jù)和索引。在專用的數(shù)據(jù)庫(kù)服務(wù)器上,這個(gè)參數(shù)最高可以設(shè)置為機(jī)器物理內(nèi)存量的 80%。 | Shared_buffers緩存。在默認(rèn)情況下分配 64 個(gè)緩沖區(qū)。默認(rèn)的塊大小是 8K。可以通過設(shè)置 postgresql.conf 文件中的 shared_buffers 參數(shù)來更新緩沖區(qū)緩存。 |
| 數(shù)據(jù)庫(kù)連接 | 客戶機(jī)使用 CONNECT 或 USE 語(yǔ)句連接數(shù)據(jù)庫(kù),這時(shí)要指定數(shù)據(jù)庫(kù)名,還可以指定用戶 id 和密碼。使用角色管理數(shù)據(jù)庫(kù)中的用戶和用戶組。 | 客戶機(jī)使用 connect 語(yǔ)句連接數(shù)據(jù)庫(kù),這時(shí)要指定數(shù)據(jù)庫(kù)名,還可以指定用戶 id 和密碼。使用角色管理數(shù)據(jù)庫(kù)中的用戶和用戶組。 |
| 身份驗(yàn)證 | MySQL 在數(shù)據(jù)庫(kù)級(jí)管理身份驗(yàn)證。 基本只支持密碼認(rèn)證。 | PostgreSQL 支持豐富的認(rèn)證方法:信任認(rèn)證、口令認(rèn)證、Kerberos 認(rèn)證、基于 Ident 的認(rèn)證、LDAP 認(rèn)證、PAM 認(rèn)證 |
| 加密 | 可以在表級(jí)指定密碼來對(duì)數(shù)據(jù)進(jìn)行加密。還可以使用 AES_ENCRYPT 和 AES_DECRYPT 函數(shù)對(duì)列數(shù)據(jù)進(jìn)行加密和解密??梢酝ㄟ^ SSL 連接實(shí)現(xiàn)網(wǎng)絡(luò)加密。 | 可以使用 pgcrypto 庫(kù)中的函數(shù)對(duì)列進(jìn)行加密/解密??梢酝ㄟ^ SSL 連接實(shí)現(xiàn)網(wǎng)絡(luò)加密。 |
| 審計(jì) | 可以對(duì) querylog 執(zhí)行 grep。 | 可以在表上使用 PL/pgSQL 觸發(fā)器來進(jìn)行審計(jì)。 |
| 查詢解釋 | 使用 EXPLAIN 命令查看查詢的解釋計(jì)劃。 | 使用 EXPLAIN 命令查看查詢的解釋計(jì)劃。 |
| 備份、恢復(fù)和日志 | InnoDB 使用寫前(write-ahead)日志記錄。支持在線和離線完全備份以及崩潰和事務(wù)恢復(fù)。需要第三方軟件才能支持熱備份。 | 在數(shù)據(jù)目錄的一個(gè)子目錄中維護(hù)寫前日志。支持在線和離線完全備份以及崩潰、時(shí)間點(diǎn)和事務(wù)恢復(fù)。 可以支持熱備份。 |
| JDBC 驅(qū)動(dòng)程序 | 可以從參考資料下載 JDBC 驅(qū)動(dòng)程序。 | 可以從參考資料下載 JDBC 驅(qū)動(dòng)程序。 |
| 表類型 | 取決于存儲(chǔ)引擎。例如,NDB 存儲(chǔ)引擎支持分區(qū)表,內(nèi)存引擎支持內(nèi)存表。 | 支持臨時(shí)表、常規(guī)表以及范圍和列表類型的分區(qū)表。不支持哈希分區(qū)表。 由于PostgreSQL的表分區(qū)是通過表繼承和規(guī)則系統(tǒng)完成了,所以可以實(shí)現(xiàn)更復(fù)雜的分區(qū)方式。 |
| 索引類型 | 取決于存儲(chǔ)引擎。MyISAM:BTREE,InnoDB:BTREE。 | 支持 B-樹、哈希、R-樹和 Gist 索引。 |
| 約束 | 支持主鍵、外鍵、惟一和非空約束。對(duì)檢查約束進(jìn)行解析,但是不強(qiáng)制實(shí)施。 | 支持主鍵、外鍵、惟一、非空和檢查約束。 |
| 存儲(chǔ)過程和用戶定義函數(shù) | 支持 CREATE PROCEDURE 和 CREATE FUNCTION 語(yǔ)句。存儲(chǔ)過程可以用 SQL 和 C++ 編寫。用戶定義函數(shù)可以用 SQL、C 和 C++ 編寫。 | 沒有單獨(dú)的存儲(chǔ)過程,都是通過函數(shù)實(shí)現(xiàn)的。用戶定義函數(shù)可以用 PL/pgSQL(專用的過程語(yǔ)言)、PL/Tcl、PL/Perl、PL/Python 、SQL 和 C 編寫。 |
| 觸發(fā)器 | 支持行前觸發(fā)器、行后觸發(fā)器和語(yǔ)句觸發(fā)器,觸發(fā)器語(yǔ)句用過程語(yǔ)言復(fù)合語(yǔ)句編寫。 | 支持行前觸發(fā)器、行后觸發(fā)器和語(yǔ)句觸發(fā)器,觸發(fā)器過程用 C 編寫。 |
| 系統(tǒng)配置文件 | my.conf | Postgresql.conf |
| 數(shù)據(jù)庫(kù)配置 | my.conf | Postgresql.conf |
| 客戶機(jī)連接文件 | my.conf | pg_hba.conf |
| XML 支持 | 有限的 XML 支持。 | 有限的 XML 支持。 |
| 數(shù)據(jù)訪問和管理服務(wù)器 | OPTIMIZE TABLE—— 回收未使用的空間并消除數(shù)據(jù)文件的碎片 myisamchk -analyze—— 更新查詢優(yōu)化器所使用的統(tǒng)計(jì)數(shù)據(jù)(MyISAM 存儲(chǔ)引擎) mysql—— 命令行工具 MySQL Administrator—— 客戶機(jī) GUI 工具 | Vacuum—— 回收未使用的空間 Analyze—— 更新查詢優(yōu)化器所使用的統(tǒng)計(jì)數(shù)據(jù) psql—— 命令行工具 pgAdmin—— 客戶機(jī) GUI 工具 |
| 并發(fā)控制 | 支持表級(jí)和行級(jí)鎖。InnoDB 存儲(chǔ)引擎支持 READ_COMMITTED、READ_UNCOMMITTED、REPEATABLE_READ 和 SERIALIZABLE。使用 SET TRANSACTION ISOLATION LEVEL 語(yǔ)句在事務(wù)級(jí)設(shè)置隔離級(jí)別。 | 支持表級(jí)和行級(jí)鎖。支持的 ANSI 隔離級(jí)別是 Read Committed(默認(rèn) —— 能看到查詢啟動(dòng)時(shí)數(shù)據(jù)庫(kù)的快照)和 Serialization(與 Repeatable Read 相似 —— 只能看到在事務(wù)啟動(dòng)之前提交的結(jié)果)。使用 SET TRANSACTION 語(yǔ)句在事務(wù)級(jí)設(shè)置隔離級(jí)別。使用 SET SESSION 在會(huì)話級(jí)進(jìn)行設(shè)置。 |
MySQL相對(duì)于PostgreSQL的劣勢(shì):
| MySQL | PostgreSQL |
| 最重要的引擎InnoDB很早就由Oracle公司控制。目前整個(gè)MySQL數(shù)據(jù)庫(kù)都由Oracle控制。 | BSD協(xié)議,沒有被大公司壟斷。 |
| 對(duì)復(fù)雜查詢的處理較弱,查詢優(yōu)化器不夠成熟 | 很強(qiáng)大的查詢優(yōu)化器,支持很復(fù)雜的查詢處理。 |
| 只有一種表連接類型:嵌套循環(huán)連接(nested-loop),不支持排序-合并連接(sort-merge join)與散列連接(hash join)。 | 都支持 |
| 性能優(yōu)化工具與度量信息不足 | 提供了一些性能視圖,可以方便的看到發(fā)生在一個(gè)表和索引上的select、delete、update、insert統(tǒng)計(jì)信息,也可以看到cache命中率。網(wǎng)上有一個(gè)開源的pgstatspack工具。 |
| InnoDB的表和索引都是按相同的方式存儲(chǔ)。也就是說表都是索引組織表。這一般要求主鍵不能太長(zhǎng)而且插入時(shí)的主鍵最好是按順序遞增,否則對(duì)性能有很大影響。 | 不存在這個(gè)問題。 |
| 大部分查詢只能使用表上的單一索引;在某些情況下,會(huì)存在使用多個(gè)索引的查詢,但是查詢優(yōu)化器通常會(huì)低估其成本,它們常常比表掃描還要慢。 | 不存在這個(gè)問題 |
| 表增加列,基本上是重建表和索引,會(huì)花很長(zhǎng)時(shí)間。 | 表增加列,只是在數(shù)據(jù)字典中增加表定義,不會(huì)重建表 |
| 存儲(chǔ)過程與觸發(fā)器的功能有限。可用來編寫存儲(chǔ)過程、觸發(fā)器、計(jì)劃事件以及存儲(chǔ)函數(shù)的語(yǔ)言功能較弱 | 除支持pl/pgsql寫存儲(chǔ)過程,還支持perl、python、Tcl類型的存儲(chǔ)過程:pl/perl,pl/python,pl/tcl。 也支持用C語(yǔ)言寫存儲(chǔ)過程。 |
| 不支持Sequence。 | 支持 |
| 不支持函數(shù)索引,只能在創(chuàng)建基于具體列的索引。 不支持物化視圖。 | 支持函數(shù)索引,同時(shí)還支持部分?jǐn)?shù)據(jù)索引,通過規(guī)則系統(tǒng)可以實(shí)現(xiàn)物化視圖的功能。 |
| 執(zhí)行計(jì)劃并不是全局共享的, 僅僅在連接內(nèi)部是共享的。 | 執(zhí)行計(jì)劃共享 |
| MySQL支持的SQL語(yǔ)法(ANSI SQL標(biāo)準(zhǔn))的很小一部分。不支持遞歸查詢、通用表表達(dá)式(Oracle的with 語(yǔ)句)或者窗口函數(shù)(分析函數(shù))。 | 都 支持 |
| 不支持用戶自定義類型或域(domain) | 支持。 |
| 對(duì)于時(shí)間、日期、間隔等時(shí)間類型沒有秒以下級(jí)別的存儲(chǔ)類型 | 可以精確到秒以下。 |
| 身份驗(yàn)證功能是完全內(nèi)置的,不支持操作系統(tǒng)認(rèn)證、PAM認(rèn)證,不支持LDAP以及其它類似的外部身份驗(yàn)證功能。 | 支持OS認(rèn)證、Kerberos 認(rèn)證 、Ident 的認(rèn)證、LDAP 認(rèn)證、PAM 認(rèn)證 |
| 不支持database link。有一種叫做Federated的存儲(chǔ)引擎可以作為一個(gè)中轉(zhuǎn)將查詢語(yǔ)句傳遞到遠(yuǎn)程服務(wù)器的一個(gè)表上,不過,它功能很粗糙并且漏洞很多 | 有dblink,同時(shí)還有一個(gè)dbi-link的東西,可以連接到oracle和mysql上。 |
| Mysql Cluster可能與你的想象有較大差異。開源的cluster軟件較少。 復(fù)制(Replication)功能是異步的,并且有很大的局限性.例如,它是單線程的(single-threaded),因此一個(gè)處理能力更強(qiáng)的Slave的恢復(fù)速度也很難跟上處理能力相對(duì)較慢的Master. | 有豐富的開源cluster軟件支持。 |
| explain看執(zhí)行計(jì)劃的結(jié)果簡(jiǎn)單。 | explain返回豐富的信息。 |
| 類似于ALTER TABLE或CREATE TABLE一類的操作都是非事務(wù)性的.它們會(huì)提交未提交的事務(wù),并且不能回滾也不能做災(zāi)難恢復(fù) | DDL也是有事務(wù)的。 |
PostgreSQL主要優(yōu)勢(shì):
1. PostgreSQL完全免費(fèi),而且是BSD協(xié)議,如果你把PostgreSQL改一改,然后再拿去賣錢,也沒有人管你,這一點(diǎn)很重要,這表明了PostgreSQL數(shù)據(jù)庫(kù)不會(huì)被其它公司控制。oracle數(shù)據(jù)庫(kù)不用說了,是商業(yè)數(shù)據(jù)庫(kù),不開放。而MySQL數(shù)據(jù)庫(kù)雖然是開源的,但現(xiàn)在隨著SUN被oracle公司收購(gòu),現(xiàn)在基本上被oracle公司控制,其實(shí)在SUN被收購(gòu)之前,MySQL中最重要的InnoDB引擎也是被oracle公司控制的,而在MySQL中很多重要的數(shù)據(jù)都是放在InnoDB引擎中的,反正我們公司都是這樣的。所以如果MySQL的市場(chǎng)范圍與oracle數(shù)據(jù)庫(kù)的市場(chǎng)范圍沖突時(shí),oracle公司必定會(huì)犧牲MySQL,這是毫無疑問的。
2. 與PostgreSQl配合的開源軟件很多,有很多分布式集群軟件,如pgpool、pgcluster、slony、plploxy等等,很容易做讀寫分離、負(fù)載均衡、數(shù)據(jù)水平拆分等方案,而這在MySQL下則比較困難。
3. PostgreSQL源代碼寫的很清晰,易讀性比MySQL強(qiáng)太多了,懷疑MySQL的源代碼被混淆過。所以很多公司都是基本PostgreSQL做二次開發(fā)的。
4. PostgreSQL在很多方面都比MySQL強(qiáng),如復(fù)雜SQL的執(zhí)行、存儲(chǔ)過程、觸發(fā)器、索引。同時(shí)PostgreSQL是多進(jìn)程的,而MySQL是線程的,雖然并發(fā)不高時(shí),MySQL處理速度快,但當(dāng)并發(fā)高的時(shí)候,對(duì)于現(xiàn)在多核的單臺(tái)機(jī)器上,MySQL的總體處理性能不如PostgreSQL,原因是MySQL的線程無法充分利用CPU的能力。
目前只想到這些,以后想到再添加,歡迎大家拍磚。
PostgreSQL與oracle或InnoDB的多版本實(shí)現(xiàn)的差別
PostgreSQL與oracle或InnoDB的多版本實(shí)現(xiàn)最大的區(qū)別在于最新版本和歷史版本是否分離存儲(chǔ),PostgreSQL不分,而oracle和InnoDB分,而innodb也只是分離了數(shù)據(jù),索引本身沒有分開。
PostgreSQL的主要優(yōu)勢(shì)在于:
1. PostgreSQL沒有回滾段,而oracle與innodb有回滾段,oracle與Innodb都有回滾段。對(duì)于oracle與Innodb來說,回滾段是非常重要的,回滾段損壞,會(huì)導(dǎo)致數(shù)據(jù)丟失,甚至數(shù)據(jù)庫(kù)無法啟動(dòng)的嚴(yán)重問題。另由于PostgreSQL沒有回滾段,舊數(shù)據(jù)都是記錄在原先的文件中,所以當(dāng)數(shù)據(jù)庫(kù)異常crash后,恢復(fù)時(shí),不會(huì)象oracle與Innodb數(shù)據(jù)庫(kù)那樣進(jìn)行那么復(fù)雜的恢復(fù),因?yàn)閛racle與Innodb恢復(fù)時(shí)同步需要redo和undo。所以PostgreSQL數(shù)據(jù)庫(kù)在出現(xiàn)異常crash后,數(shù)據(jù)庫(kù)起不來的幾率要比oracle和mysql小一些。
2. 由于舊的數(shù)據(jù)是直接記錄在數(shù)據(jù)文件中,而不是回滾段中,所以不會(huì)象oracle那樣經(jīng)常報(bào)ora-01555錯(cuò)誤。
3. 回滾可以很快完成,因?yàn)榛貪L并不刪除數(shù)據(jù),而oracle與Innodb,回滾時(shí)很復(fù)雜,在事務(wù)回滾時(shí)必須清理該事務(wù)所進(jìn)行的修改,插入的記錄要?jiǎng)h除,更新的記錄要更新回來(見row_undo函數(shù)),同時(shí)回滾的過程也會(huì)再次產(chǎn)生大量的redo日志。
4. WAL日志要比oracle和Innodb簡(jiǎn)單,對(duì)于oracle不僅需要記錄數(shù)據(jù)文件的變化,還要記錄回滾段的變化。
PostgreSQL的多版本的主要劣勢(shì)在于:
1、最新版本和歷史版本不分離存儲(chǔ),導(dǎo)致清理老舊版本需要作更多的掃描,代價(jià)比較大,但一般的數(shù)據(jù)庫(kù)都有高峰期,如果我們合理安排VACUUM,這也不是很大的問題,而且在PostgreSQL9.0中VACUUM進(jìn)一步被加強(qiáng)了。
2、由于索引中完全沒有版本信息,不能實(shí)現(xiàn)Coverage index scan,即查詢只掃描索引,直接從索引中返回所需的屬性,還需要訪問表。而oracle與Innodb則可以;
進(jìn)程模式與線程模式的對(duì)比
PostgreSQL和oracle是進(jìn)程模式,MySQL是線程模式。
進(jìn)程模式對(duì)多CPU利用率比較高。
進(jìn)程模式共享數(shù)據(jù)需要用到共享內(nèi)存,而線程模式數(shù)據(jù)本身就是在進(jìn)程空間內(nèi)都是共享的,不同線程訪問只需要控制好線程之間的同步。
線程模式對(duì)資源消耗比較少。
所以MySQL能支持遠(yuǎn)比oracle多的更多的連接。
對(duì)于PostgreSQL的來說,如果不使用連接池軟件,也存在這個(gè)問題,但PostgreSQL中有優(yōu)秀的連接池軟件軟件,如pgbouncer和pgpool,所以通過連接池也可以支持很多的連接。
堆表與索引組織表的的對(duì)比
Oracle支持堆表,也支持索引組織表
PostgreSQL只支持堆表,不支持索引組織表
Innodb只支持索引組織表
索引組織表的優(yōu)勢(shì):
表內(nèi)的數(shù)據(jù)就是按索引的方式組織,數(shù)據(jù)是有序的,如果數(shù)據(jù)都是按主鍵來訪問,那么訪問數(shù)據(jù)比較快。而堆表,按主鍵訪問數(shù)據(jù)時(shí),是需要先按主鍵索引找到數(shù)據(jù)的物理位置。
索引組織表的劣勢(shì):
索引組織表中上再加其它的索引時(shí),其它的索引記錄的數(shù)據(jù)位置不再是物理位置,而是主鍵值,所以對(duì)于索引組織表來說,主鍵的值不能太大,否則占用的空間比較大。
對(duì)于索引組織表來說,如果每次在中間插入數(shù)據(jù),可能會(huì)導(dǎo)致索引分裂,索引分裂會(huì)大大降低插入的性能。所以對(duì)于使用innodb來說,我們一般最好讓主鍵是一個(gè)無意義的序列,這樣插入每次都發(fā)生在最后,以避免這個(gè)問題。
由于索引組織表是按一個(gè)索引樹,一般它訪問數(shù)據(jù)塊必須按數(shù)據(jù)塊之間的關(guān)系進(jìn)行訪問,而不是按物理塊的訪問數(shù)據(jù)的,所以當(dāng)做全表掃描時(shí)要比堆表慢很多,這可能在OLTP中不明顯,但在數(shù)據(jù)倉(cāng)庫(kù)的應(yīng)用中可能是一個(gè)問題。
PostgreSQL9.0中的特色功能:
PostgreSQL中的Hot Standby功能
也就是standby在應(yīng)用日志同步時(shí),還可以提供只讀服務(wù),這對(duì)做讀寫分離很有用。這個(gè)功能是oracle11g才有的功能。
PostgreSQL異步提交(Asynchronous Commit)的功能:
這個(gè)功能oracle中也是到oracle11g R2才有的功能。因?yàn)樵诤芏鄳?yīng)用場(chǎng)景中,當(dāng)宕機(jī)時(shí)是允許丟失少量數(shù)據(jù)的,這個(gè)功能在這樣的場(chǎng)景中就特別合適。在PostgreSQL9.0中把synchronous_commit設(shè)置為false就打開了這個(gè)功能。需要注意的是,雖然設(shè)置為了異步提交,當(dāng)主機(jī)宕機(jī)時(shí),PostgreSQL只會(huì)丟失少量數(shù)據(jù),異步提交并不會(huì)導(dǎo)致數(shù)據(jù)損壞而數(shù)據(jù)庫(kù)起不來的情況。MySQL中沒有聽說過有這個(gè)功能。
PostgreSQL中索引的特色功能:
PostgreSQL中可以有部分索引,也就是只能表中的部分?jǐn)?shù)據(jù)做索引,create index 可以帶where 條件。同時(shí)PostgreSQL中的索引可以反向掃描,所以在PostgreSQL中可以不必建專門的降序索引了。