PostgreSQL

PostgreSQL（ˌ POHST）是一款功能全面且開源的關係型資料庫管理系統，憑藉其卓越的擴展能力和對SQL標準的嚴格遵循而廣受讚譽。作為一款成熟的資料庫系統，它不僅支持符合ACID特性的事務處理，還集成了自動更新的視圖、物化視圖、觸發器、外鍵約束以及存儲過程等一系列強大功能。

PostgreSQL能夠在Windows、Linux、macOS等主流作業系統上流暢運行，其應用範圍極為廣泛，無論是單機應用、大規模數據倉庫，還是數據湖、高並發Web服務等場景，都能應對自如。

PostgreSQL的核心開發工作由全球開發組（PostgreSQL Global Development Group）負責，他們專注於資料庫引擎及其核心組件的研發與優化。在這個核心團隊之外，還活躍著一個生機勃勃的開發者社區和生態系統，他們為PostgreSQL提供了眾多增強功能，填補了通常由商業資料庫供應商所提供的功能空缺。這些擴展涵蓋了地理空間數據處理、時序資料庫支持等特殊領域，以及模擬其他資料庫產品的兼容層。

同時，第三方開發者也貢獻了各種使用者和機器接口功能，包括圖形使用者界面、負載均衡和高可用性工具集等。

儘管這個龐大的支持網路（涵蓋個人、企業、產品和項目）並非PostgreSQL開發組的一部分，但它們共同促進了PostgreSQL生態系統的繁榮發展，對資料庫的推廣與應用起到了至關重要的作用。

這款資料庫系統最初名為POSTGRES，以彰顯其作為加州大學柏克萊分校Ingres資料庫系統繼承者的身份。1996年，為了體現其對SQL的支持，項目更名為PostgreSQL。經過2007年的一次評審，開發團隊決定保留PostgreSQL這個名稱和Postgres這個簡稱。

## 歷史

PostgreSQL經歷了長時間的演變。該項目最初始於加利福尼亞大學伯克利分校的Ingres計劃。這個計劃的領導者麥可·斯通布雷克在1982年離開加利福尼亞大學伯克利分校以推動Ingres的商業化，但最後還是返回了學術界。在1985年返回伯克利之後，斯通布雷克開始了post-Ingres計劃，致力於解決1980年代早期資料庫系統所存在的一些問題。Postgres和Ingres的代碼庫自始至終保持完全分離。

新項目Postgres的目的是通過引入最少量的必要功能，以完整支持所需要的類型。這些功能包括類型定義和完整描述數據關係的能力。完整描述數據關係的能力先前雖已廣泛使用，但仍需要由使用者自行維護。Postgres的資料庫能夠「理解」關係，並可以通過特定規則，以自然的方式在相關的表中檢索資訊。

從1986年開始，該項目組發表了一些描述這一系統基本原理的論文，並在1988年實現並運行了一個Demo版本。項目組在1989年六月向少數使用者發行了版本1.0，隨後在1990年6月發行了帶有全新規則系統的版本2.0。1991年的版本3.0再次重寫了規則系統，並增加了對多個存儲管理器的支持與改進的查詢引擎。Postgres在1993年開始擁有大量使用者，這些使用者提供了大量的功能與優化建議。但是在發行了作為細節修正的版本4.0之後，Postgres計劃就終止了。

儘管Postgres計劃正式的終止了，BSD許可證（Postgres遵守BSD許可證發行）卻使開發者們得以獲取原始碼並進一步開發系統。1994年，兩個加利福尼亞大學伯克利分校的研究生 Andrew Yu和Jolly Chen 增加了一個SQL語言解釋器來替代早先的基於Ingres的QUEL系統，建立了Postgres95。代碼隨後被發布到網際網路上供全世界使用。Postgres95在1996年被重命名為PostgreSQL以便突出該資料庫全新的SQL查詢語言。

PostgreSQL首次發行即選擇6.0作為其版本號，由來自世界各地的資料庫開發者和志願者們，通過網際網路進行軟體的維護。在2005年1月19日，PostgreSQL發行了版本8.0。自版本8.0之後，PostgreSQL得以藉助原生方式運行於Windows系統之下。

儘管許可證允許PostgreSQL被用於商業用途，PostgreSQL卻並沒有像Ingres那樣快速的被商業化。在2005年1月，PostgreSQL才收到了它來自資料庫廠商的第一份援助。Pervasive Software宣布了對PostgreSQL的商業支持和社區參與。

但其實在此之前，就已經有一些公司開始對PostgreSQL伸出援手。2000年，前Red Hat投資者籌組了一間名為Great Bridge的公司來商業化PostgreSQL，與其他商用資料庫廠商展開競爭。Great Bridge資助了好幾位PostgreSQL開發者，並且貢獻了許多資源給社區。然而到了2001年末，Great Bridge卻終止了營運，一部分原因在於PostgreSQL在被商業化後，其市場狀況並不理想。

2001年，Command Prompt, Inc.發布了Mammoth PostgreSQL，這是最老牌的PostgreSQL商業軟體。他們通過對開發者的贊助，和開發PL/Perl、PL/php等PostgreSQL在各語言中的實現，以及維護PostgreSQL Build Farm等方式來支援PostgreSQL社群。

2005年1月，PostgreSQL接到了來自另一間資料庫廠商Pervasive Software的支持，該公司以常見於Novell NetWare平台的Btrieve產品而聞名。他們宣布了進行商業支援和對社群的參與。但在他們成功商業化PostgreSQL一段時間後的2006年7月，Pervasive Software離開了PostgreSQL的支援市場。

在2005年中，兩間其他的公司宣佈商業化PostgreSQL，分別進入不同的利基市場。EnterpriseDB宣布將專注於讓使用Oracle的應用程式能更容易的在PostgreSQL上運行。Greenplum則專注貢獻在資料倉儲和商業智慧的應用程式，尤其以BizGres專案著稱。

2005年10月，昇陽的軟體部門執行副總裁John Loiacono談論到："我們不會去OEM微軟的產品，我們正關注著PostgreSQL"，儘管當時並沒有任何規格釋出。到了2005年11月，昇陽宣布將支援PostgreSQL。2006年6月，Solaris 10包含PostgreSQL一起發佈。

至於PostgreSQL專案本身，他繼續著每年一個主要版本發佈，以及次要的除錯版本發佈，這些發布全都遵守BSD授權。

## 描述

如果很粗略地觀察PostgreSQL，會覺得這個資料庫系統和其它資料庫很類似。因為PostgreSQL使用SQL語言來執行資料的查詢。這些資料通過外鍵聯繫在一起，以一系列表格的形式存在。PostgreSQL相對於競爭者的主要優勢為可編程性：對於使用資料庫資料的實際應用，PostgreSQL讓開發與使用變得更簡單。

SQL數據在「平面表格」中存儲簡單的數據類型，需要使用者使用查詢把有關的資訊收集在一起。這與應用和使用者利用數據自身的方式相對立：典型的使用帶有豐富數據類型的高級語言，在其中所有有關的數據作為它自己的一個完整單元來操作。典型的稱呼為記錄或對象（依據各自語言）。

轉換來自SQL世界的資訊到面向對象編程世界體現得很困難，因為兩者有非常不同的數據組織的模型。工業界把這個問題稱為對象關係不匹配：從一個模型映射到另一個要花費項目開發者40%的時間。一些映射解決方案，典型的稱為對象關係映射，致力於這個問題，但是它們花費很多並有自身的問題，導致糟糕的性能或強制所有的數據訪問通過映射所支持的一種語言來進行。

PostgreSQL可以直接在資料庫中解決很多這類問題。PostgreSQL允許用戶定義基於正規的SQL類型的新類型，允許資料庫自身理解複雜數據。例如，你可以定義一個`address`來組合一些事物如街道編號、城市和國度的字串。從這一點上你可以輕易地建立把保存地址所需要的所有欄位包含在一個單一行列中的表。

PostgreSQL還允許類型包括繼承，這是在面向對象編程中的主要概念。例如，你可以定義`post_code`類型，並接著基於它建立`us_zip_code`和`canadian_postal_code`。在資料庫中的address就可以採用`us_address`或者`canadian_address`形式，而特定的規則可以在各自情況下驗證數據。在PostgreSQL的早期版本中，實現新類型需要寫C擴展並把它們編譯到資料庫伺服器中；在版本7.4中，通過`CREATE DOMAIN`建立和使用定製類型變得很容易了。

資料庫自身的編程可以從使用函數上獲得巨大的利益。多數SQL系統允許用戶寫存儲過程，它是其他SQL語句可以調用的一塊SQL代碼。但是SQL自身仍舊不適合作為程式語言，而且SQL使用者在構造複雜邏輯時要經歷巨大的困難。更糟糕的是，SQL自身不支持很多的程式語言中最基本的操作，比如分支和循環。每個廠商都轉而寫它們自己對SQL語言的擴展來增加這些特徵，而這種擴展不是必須跨越資料庫平台操作。

在PostgreSQL中程式設計師可以用一組可觀的支持語言中任何一種來寫這種邏輯。

- 類似於Oracle的過程語言PL/SQL的叫做PgSQL的內置語言，在處理查詢密集的過程時提供了獨特的優勢。
- 流行腳本語言比如Perl、Python、Tcl和Ruby的包裝器，允許利用它們在字串處理和連接到廣闊的外部函數庫的力量。
- 需要把複雜邏輯編譯到機器代碼所能提供的高性能的過程可以利用C或C++。
- 在更加深奧的方面，R統計語言的處理器允許資料庫查詢利用它的一組豐富的統計函數。

程式設計師可以把代碼作為函數插入伺服器中，它是使代碼類似於存儲過程的一個小包裝器。以這種方式SQL代碼可以調用（比如）C代碼或反之。

- 性能增進，因為資料庫引擎在一個時間一個地方調用所有的邏輯，減少了在客戶和伺服器之間的來回往返的次數。
- 可靠性增進，因為數據驗證代碼集中到一個地方，就在伺服器上，而不用依賴在多個客戶應用中的同步邏輯，它們甚至可能以多種程式語言寫成。
- 通過向伺服器增加有用的抽象，客戶代碼可以變得更短小和簡單。

這些優勢合起來可以證實PostgreSQL從編程角度是最高級的資料庫系統。使用PostgreSQL可以顯著的減少很多項目的整體編程時間，這種優勢隨著項目複雜而增長。

## 特徵

### 函數

通過函數，可以在資料庫伺服器端執行指令程序。儘管這樣的指令程序可以使用基本的SQL語句寫成，但是由於其缺乏流程控制等功能，所以在PostgreSQL中引入了使用其它程序語言編寫函數的能力，包括：

- 一個內置的名為pgSQL的過程語言，類似於Oracle的PL/SQL。
- 包括PL/Perl，PL/PHP，PL/Python，PL/Ruby，PL/sh，PL/Tcl與PL/Scheme在內的腳本語言。
- 編譯語言：C，C++，或Java（通過PL/Java）。
- R統計語言PL/R。

以上部分的語言，甚至可以在觸發器內執行。PostgreSQL支持行返回函數：它們的輸出是一系列行類型數據的集合，可以在查詢中當作表來使用。函數也可以被定義成以創建者或者調用者的身份運行。在某些場合，或者其他的資料庫產品中，函數也會被稱為「存儲過程」，但技術上這兩者並未有太大分別。

### 索引

在PostgreSQL中，使用者可以自定義索引方法，或使用內置的B樹，哈希表與GiST索引。PostgreSQL的索引功能同時也具有以下功能：

- 反向索引檢索：無須額外的索引就能實現類似`ORDER BY ''field'' DESC`的操作。
- 表達式索引：可以建立基於表達式值而非數值或列的索引。
- 部分索引：僅索引表的部分，可以通過在`CREATE INDEX`語句口添加`WHERE`從句以創建更小的索引。
- 位圖索引掃描：從8.1版開始支持此功能。該功能將讀取多個索引，生成表示它們之間符合查詢標準的多元組交集的位圖。這樣解決了混合索引的問題。在一個具有20列的表中，理論上能創建20! 個索引，在實際應用中並不實用。使用位圖索引掃描後，在每次查詢時，它將能把約束條件中所涉及列各自的索引進行任意的排列組合。

### 觸發器

觸發器是由SQL語句查詢所觸發的事件。如：一個INSERT語句可能觸發一個檢查數據完整性的觸發器。觸發器通常由INSERT或UPDATE語句觸發。

在PostgreSQL中，可在數據表上設置觸發器，但無法在視圖中設置(對視圖的UPDATE或者INSERT操作可以使用規則（RULE）定義）。多個觸發器可依據字母順序依次執行。此外，除了使用內嵌的PL/PgSQL語言之外，觸發器的函數也可以用PL/Perl，PL/Python等語言編寫。

### 多版本並發控制

PostgreSQL使用多版本並發控制（MVCC，Multiversion concurrency control）系統進行並發控制，該系統向每個使用者提供了一個資料庫的「快照」，使用者在事務內所作的每個修改，對於其他的使用者都不可見，直到該事務成功提交。這從很大程度上減少了對讀取鎖的依賴，同時保證了資料庫高效地符合ACID原則。

### 規則

規則（RULE）允許一個查詢能被重寫，通常用來實現對視圖（VIEW）的操作，如插入（INSERT）、更新（UPDATE）、刪除（DELETE）。

### 數據類型

PostgreSQL內置豐富的數據類型，包括：

- 任意精度的數值
- 無限制長度文本
- 幾何圖元
- IP位址與IPv6地址
- 無類域間路由地址塊，MAC地址
- 陣列
- JSON數據
- 枚舉類型
- XML數據 (需要在PostgreSQL源碼編譯時指定 "--with-libxml"選項)

此外，使用者可以創建自定義數據類型，通常通過PostgreSQL的GiST機制，它們也能被很好得索引，比如PostGIS地理資訊系統的數據類型。

### 使用者定義對象

使用者可以為資料庫內幾乎所有的對象定義新的類型，包括：

- 索引
- 操作符（可重載現有操作符。）
- 聚合函數
- 數據域
- 數據類型轉換
- 會話（編碼轉換）

### 繼承

數據表的結構及屬性可從一個「父」表中繼承，數據將在兩者間共享。對子表中數據的插入或者刪除也將在父表中呈現，同樣，對父表作出的修改，比如新增列等操作也會導致子表產生相應的變更。該功能尚未完全實現，實際上，表的約束尚不能繼承。比如，在一張外聯參考了父表id欄位的表中，插入一條具有子表中某條記錄id數據的記錄會導致失敗，因為PostgreSQL在對父表的外鍵約束檢查中不會檢查子表的內容。

### 其他功能

- 關係完整性約束：包括外鍵，列約束與行檢查
- 視圖
- 內、外（全、左、右）連接
- 子查詢
- 事務處理
- 支持大部分SQL:2003標準的主要特徵。不支持部分特徵，和將來支持的特徵，可至已有版本手冊中查詢。
- SSL加密連接
- 二進位／文本大對象的存儲
- 在線備份
- 數據域
- 表分區
- 表空間
- 保存點
- 時刻點恢復
- 二階段提交
- TOAST（The Oversized-Attribute Storage Technique，超大屬性存儲技術）用以透明地將超大表屬性（如大MIME附件或XML消息）壓縮後存儲至獨立的區域
- 正則表達式

### 資料庫管理及開發工具

- phpPgAdmin基於php語言寫的用於管理PostgreSQL資料庫的程序
- PgAdmin另外一個用於管理PostgreSQL資料庫的軟體

### 擴展

- 地理數據對象：PostGIS GPL
- 向量數據： pgvector
- 全文檢索：通過Tsearch2GPL或OpenFTS，將在8.3版本中內嵌Tsearch2
- 多種異步主／從複製方案，包括Slony-I（BSD授權），Mammoth Replicator
- XML/XSLT支持contrib軟體包中的XPath擴展GPL
- 機器學習：MADlibASF，由Apache基金會的支持的頂級開源項目；集成大量傳統數學分析統計、圖計算以及一些常見的機器學習的演算法

## 知名客戶

- .org域名庫
- The American Chemical Society
- Chicagocrime.org
- Skype
- Penny Arcade
- IMDB
- Sony Online
- 美國勞工部
- Wisconsin Circuit Court Access with 6 * 180GB DBs replicated in real time
- OpenACS and .LRN
- Evergreen－一個開放原始碼（GNU通用公共許可證）的集成圖書館系統
- GNU Health

## 版本

PostgreSQL - Red Hat Edition是由Red Hat製作之分支版本，又稱Red Hat Database。

## 參閱

- 關係資料庫管理系統
- 關係型資料庫管理系統列表
- 關係型資料庫管理系統對比
- 對象資料庫管理系統
- 對象資料庫管理系統列表
- 對象資料庫管理系統對比

## 外部連結

- PostgreSQL國際官方網站
- PostgreSQL 台灣使用者社群
- PostgreSQL :：國際中文社群部落格：:
- PostgreSQL文檔
- SourceForge上PostgreSQL的相關項目
- PgFoundry-PostgreSQL相關項目網站
- Open Source Database Network
- Database Journal的PostgreSQL專欄
- PostgreSQL中文推廣教學平台 - Mammoth

## 基本資料

- 開發者：PostgreSQL Global Development Group
- 狀態：開發中
- 發行日期：1996年7月8日
- 作業系統：Linux, Windows, FreeBSD, OpenBSD, NetBSD, macOS, AIX, HP/UX, Solaris 等
- 平台：x86, x86_64, IA64, PowerPC, PowerPC 64, S/390, S/390x, Sparc, Sparc 64, ARM, MIPS, MIPSEL, PA-RISC 等
- 程式語言：C語言
- 語言：英語
- 類型：關聯式資料庫
- 許可協議：PostgreSQL授權