# PostgreSQL 常見問題（FAQ）

最近更新：2007 年 2 月 8 日 星期二 22:43:13 EST
中文版最近更新：2007 年 2 月 12 日 星期一 12:00:04 CST

當前維護人員：Bruce Momjian (pgman@candle.pha.pa.us)
正體中文版維護人員：郭朝益(ChaoYi, Kuo)（kuo.chaoyi@gmail.com）

本文檔的最新版本可以在 http://www.postgresql.org/files/documentation/faqs/FAQ.html 查看。

與作業系統平台相關的問題可在 http://www.postgresql.org/docs/faq/ 裡找到答案。

## 常見問題

1.1)PostgreSQL 是什麼？該怎麼發音？
1.2)誰控制和管理PostgreSQL ？
1.3)PostgreSQL的版權是什麼？
1.4)PostgreSQL可以運行在哪些作業系統平台上？
1.5)我從哪裡能得到PostgreSQL？
1.6)最新版的 PostgreSQL 是什麼？
1.7)我從哪裡能得到對 PostgreSQL 的支持？
1.8)我如何提交一個 BUG 報告？
1.9)我如何瞭解已知的 BUG 或暫缺的功能？
1.10)能夠獲取的最新文檔有哪些？
1.11)我應該怎樣學習 SQL ？
1.12)如何提交補丁或是加入開發隊伍？
1.13)PostgreSQL 和其他資料庫系統比起來如何？
1.14)PostgreSQL 可以處理最近各個國家夏時制的變化嗎？

## 用戶客戶端問題

2.1)我們可以用什麼語言和 PostgreSQL 進行溝通？
2.2)有什麼工具可以把 PostgreSQL 用於 Web 頁面？
2.3)PostgreSQL 擁有圖形用戶界面(GUI)嗎？

## 系統管理問題

3.1)我怎樣才能把 PostgreSQL 裝在 /usr/local/pgsql 以外的地方？
3.2)我如何控制來自其他電腦的連接？
3.3)我怎樣調整資料庫伺服器以獲得更好的性能？
3.4)PostgreSQL 裡可以獲得什麼樣的調試特性？
3.5)為什麼在試圖連接登錄時收到「Sorry, too many clients」 訊息？
3.6)PostgreSQL 的升級過程有哪些內容？
3.7)(使用 PostgreSQL )我需要使用什麼電腦硬體？

## 操作問題

4.1) 如何只選擇一個查詢結果的頭幾行？或是隨機的一行？
4.2) 如何查看表、索引、資料庫以及用戶的定義？如何查看 psql 裡用到的查詢指令並顯示它們？
4.3) 如何更改一個欄位的資料類型？
4.4) 單筆記錄，單一表，一個資料庫的最大限制是多少？
4.5) 存儲一個典型的文本文件裡的資料需要多少磁碟空間？
4.6) 為什麼我的查詢很慢？為什麼這些查詢沒有利用索引？
4.7) 我如何才能看到查詢優化器是怎樣評估處理我的查詢的？
4.8) 我怎樣做正則表達式搜索和大小寫無關的正則表達式查找？怎樣利用索引進行大小寫無關查找？
4.9) 在一個查詢裡，我怎樣檢測一個欄位是否為 NULL？我如何才能準確排序而不論某欄位是否含NULL值？
4.10) 各種字符類型之間有什麼不同？
4.11.1) 我怎樣創建一個序列號型或是自動遞增的欄位？
4.11.2) 我如何獲得一個插入的序列號的值？
4.11.3) 同時使用 currval() 會導致和其他用戶的衝突情況嗎？
4.11.4) 為什麼不在事務異常中止後重用序列號呢？為什麼在序列號欄位的取值中存在間斷呢？
4.12) 什麼是 OID？什麼是 CTID ？
4.13) 為什麼我收到錯誤資訊「ERROR: Memory exhausted in AllocSetAlloc()」？
4.14) 我如何才能知道所運行的 PostgreSQL 的版本？
4.15) 我如何創建一個預設值是當前時間的欄位？
4.16) 如何執行外連接（outer join）查詢？
4.17) 如何執行涉及多個資料庫的查詢？
4.18) 如何讓函數返回多行或多列資料？
4.19) 為什麼我在使用 PL/PgSQL 函數存取臨時表時會收到錯誤資訊「relation with OID ##### does not exist」？
4.20) 目前有哪些資料複寫(replication)方案可用？
4.21) 為何查詢結果顯示的表名或欄名與我的查詢語句中的不同？為何大寫狀態不能保留？

## 常見問題

### 1.1) PostgreSQL 是什麼？該怎麼發音？

PostgreSQL 讀作 Post-Gres-Q-L，有時候也簡稱為Postgres 。想聽一下其發音的人員可從這裡下載聲音文件： MP3 格式 。

PostgreSQL 是面向目標的關係資料庫系統，它具有傳統商業資料庫系統的所有功能，同時又含有將在下一代 DBMS 系統的使用的增強特性。PostgreSQL 是自由免費的，並且所有源代碼都可以獲得。

PostgreSQL 的開發隊伍主要為志願者，他們遍佈世界各地並通過互聯網進行聯繫，這是一個社區開發項目，它不被任何公司控制。 如想加入開發隊伍，請參見開發人員常見問題（FAQ） http://www.postgresql.org/files/documentation/faqs/FAQ_DEV.html

### 1.2) 誰控制 PostgreSQL ？

如果你在尋找PostgreSQL的掌門人，或是什麼中央委員會，或是什麼所屬公司，你只能放棄了---因為一個也不存在，但我們的確有一個 核心委員會和CVS管理組，但這些工作組的設立主要是為了進行管理工作而不是對PostgreSQL進行獨佔式控制，PostgreSQL項目是由任何人均 可參加的開發人員社區和所有用戶控制的，你所需要做的就是訂閱郵件列表，參與討論即可（要參與PostgreSQL的開發詳見 開發人員常問題 (Developer's FAQ) 獲取資訊）。

### 1.3) PostgreSQL 的版權是什麼?

PostgreSQL的發布遵從經典的 BSD 版權。它允許用戶不限目的地使用 PostgreSQL，甚至你可以銷售 PostgreSQL 而不含源代碼也可以，唯一的限制就是你不能因軟體自身問題而向我們追訴法律責任，另外就是要求所有的軟體拷貝中須包括以下版權聲明。 下面就是我們所使用的BSD版權聲明內容：

PostgreSQL 資料庫管理系統

部分版權（c）1996-2005，PostgreSQL 全球開發小組，部分版權（c）1994-1996 加州大學董事

（Portions copyright (c) 1996-2005,PostgreSQL Global Development Group Portions Copyright (c) 1994-6 Regents of the University of California）

允許為任何目的使用，拷貝，修改和分發這個軟體和它的文檔而不收取任何費用， 並且無須簽署因此而產生的證明，前提是上面的版權聲明和本段以及下面兩段文字出現在所有拷貝中。

（Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies.）

在任何情況下，加州大學都不承擔因使用此軟體及其文檔而導致的對任何當事人的直接的， 間接的，特殊的，附加的或者相伴而生的損壞，包括利益損失的責任，即使加州大學已經建議了這些損失的可能性時也是如此。

（IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.）

加州大學明確放棄任何保證，包括但不局限於某一特定用途的商業和利益的隱含保證。 這裡提供的這份軟體是基於「當作是」的基礎的，因而加州大學沒有責任提供維護，支持，更新，增強或者修改的服務。

（THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.）

### 1.4) PostgreSQL 可以運行在哪些作業系統平台上？

一般說來，任何現在對 UNIX 相容的作業系統之上都能運行 PostgreSQL 。在安裝指南裡列出了發佈時經過明確測試的平台。

PostgreSQL 也可以直接運行在基於微軟 Windows-NT 的作業系統，如 Win2000 SP4，WinXP 和 Win2003，已製作完成的安裝包可從 http://pgfoundry.org/projects/pginstaller下載，基於MSDOS的Windows作業系統 （Win95，Win98，WinMe）需要通過Cygwin模擬環境運行PostgreSQL。

同時也有一個為 Novell Netware 6 開發的版本可從 http://forge.novell.com 獲取，為OS/2(eComStation)開發的版本可從 http://hobbes.nmsu.edu/cgi-bin/h-search?sh=1&button=Search&key=postgreSQL&stype=all&sort=type&dir=%2F 下載。

### 1.5) 我從哪裡能得到 PostgreSQL？

通過瀏覽器可從 http://www.postgresql.org/ftp/ 下載，也可通過FTP，從 ftp://ftp.PostgreSQL.org/pub/ 站點下載。

### 1.6) 最新版的 PostgreSQL 是什麼？

PostgreSQL 最新的版本是版本 8.2.3 。

我們計劃每年發佈一個主要升級版本，每幾個月發佈一個小版本。

### 1.7) 我從哪裡能得到對 PostgreSQL 的支持？

PostgreSQL社區通過郵件列表為其大多數用戶提供幫助，訂閱郵件列表的主站點是 http://www.postgresql.org/community/lists/，一般情況下，先加入General 或 Bug郵件列表是一個較好的開始。

主要的IRC頻道是在FreeNode(irc.freenode.net)的#postgresql，為了連上此頻道，可以使用 UNIX 程序 irc，其指令格式： irc -c '#postgresql' "$USER" irc.freenode.net ，或者使用其他IRC客戶端程序。在此網絡中還存在一個 PostgreSQL 的西班牙頻道(#postgersql-es)和法語頻道 (#postgresql-fr)。同樣地，在 EFNET 上也有一個 PostgreSQL 的交流頻道。

可提供商業支持的公司列表可在 http://techdocs.postgresql.org/companies.php 瀏覽。

### 1.8) 我如何提交一個 BUG 報告？

可訪問 http://www.postgresql.org/support/submitbug，填寫 Bug 上報表格即可，同樣也可訪問 ftp 站點 ftp://ftp.PostgreSQL.org/pub/ 檢查有無更新的PostgreSQL 版本或補丁。

通過使用 Bug 提交表格或是發往 PostgreSQL 郵件列表的 Bug 通常會有以下之一回覆：

- 所提交內容不是一個 Bug 及其不是 Bug 的原因。
- 所提交內容是一個已知的 Bug 並且已經加入 TODO 待處理任務列表。
- 所提交的 Bug 已在當前版本中被修正。
- 所提交的 Bug 已修正但尚未將補丁加入現在的發布軟體包。
- 請求提交者提供更詳細的資訊：
  - 作業系統
  - PostgreSQL 版本
  - 可重現 Bug 的測試案例
  - 調試資訊
  - 調試跟蹤輸出
- 所提交內容是一個新 Bug，將執行以下工作：
  - 創建一個新補丁並將其加入下一個主要版本或是小的改進版本中。
  - 此 Bug 暫時不能修正，將被加至 TODO 待處理任務列表。

### 1.9) 我如何瞭解已知的 BUG 或暫缺的功能？

PostgreSQL 支持一個擴展的 SQL:2003 的子集。參閱我們的 TODO 列表，瞭解已知 Bug 列表、暫缺的功能和將來的開發計劃。

要求增加新功能的申請通常會收到以下之一的回覆：

- 該功能已加入 TODO 待處理任務列表。
- 該功能不是必須的，因為：
  - 它是現有的且符合 SQL 標準的某功能的重複。
  - 該功能性會大大增加代碼的複雜程序，而帶來的好處是微不足道的。
  - 該功能是不安全或是不可靠的。
- 該功能將被加入 TODO 待處理任務列表。

PostgreSQL 不使用 Bug 跟蹤系統，因為我們發現在郵件列表中直接回覆以及保證 TODO 任務列表總是處於最新狀態的方式工作效率會更高一些。事實上，Bug不會在我們的軟體中存在很長時間， 對影響很多用戶的Bug也總是很快會被修正。唯一能找到所有改進、提高和修正的地方是 CVS 的日誌資訊，即使是在軟體新版本的發布資訊中也不會列出每一處的軟體更新。

### 1.10) 能夠獲取的最新文檔有哪些？

PostgreSQL 包含大量的文檔，主要有詳細的參考手冊，手冊頁和一些的測試例子。參見 /doc 目錄（譯註：應為 $PGHOME/doc）。 你還可以在線瀏覽 PostgreSQL 的手冊，其網址是：http://www.PostgreSQL.org/docs。

有兩本關於PostgreSQL的書在線提供，在 http://www.postgresql.org/docs/books/awbook.html 和 http://www.commandprompt.com/ppbook/ 。 也有大量的 PostgreSQL 書籍可供購買，其中最為流行的一本是由 Korry Douglas 編寫的。在 http://techdocs.PostgreSQL.org/techdocs/bookreviews.php上 上有大量有關 PostgreSQL 書籍的簡介。 在 http://techdocs.PostgreSQL.org/ 上收集了有關 PostgreSQL 的大量技術文章。

客戶端的命令行程序psql有一些以 \d 開頭的命令，可顯示關於類型，操作符，函數，聚合等資訊，使用 \? 可以顯示所有可用的命令。

我們的 web 站點包含更多的文檔。

### 1.11) 我應該怎樣學習 SQL ？

首先考慮上述提到的與PostgreSQL相關的書籍，另外一本是 Teach Yourself SQL in 21 Days, Second Edition，其詳細介紹的網址是 http://members.tripod.com/er4ebus/sql/index.htm， 我們的許多用戶喜歡The Practical SQL Handbook， Bowman, Judith S. 編寫，Addison-Wesley公司出版，其他的則喜歡 The Complete Reference SQL, Groff 編寫，McGraw-Hill 公司出版。

在下列網址上也有很好的教程，他們是

- http://www.intermedia.net/support/sql/sqltut.shtm
- http://sqlcourse.com.
- http://www.w3schools.com/sql/default.asp
- http://mysite.verizon.net/Graeme_Birchall/id1.html

### 1.12)如何提交補丁或是加入開發隊伍？

詳見 開發人員常見問題 (Developer's FAQ) 。

### 1.13) PostgreSQL 和其他資料庫系統比起來如何？

評價軟體有好幾種方法：功能，性能，可靠性，支持和價格。

功能
  PostgreSQL 擁有大型商用資料庫最多的功能，例如：事務，子查詢，觸發器，視圖，外鍵參考完整性和複雜的鎖定等。 我們還有一些它們沒有的特性，如用戶定義類型，繼承，規則和多版本並行控制以減少鎖的爭用等。
性能
  PostgreSQL和其他商用和開源的資料庫具有類似的性能。對某些處理它比較快，對其他一些處理它比較慢。 與其他資料庫相比，我們的性能優劣通常在 +/- 10%之間。
可靠性
  我們都知道資料庫必須是可靠的，否則它就一點用都沒有。我們努力做到發佈經過認真測試的，缺陷最少的穩定代碼。每個版本至少有一個月的 beta 測試時間，並且我們的發布歷史顯示我們可以提供穩定的，牢固的，可用於生產使用的版本。我們相信在這方面我們與其他的資料庫軟體是相當的。
支持
  我們的郵件列表提供一個非常大的開發人員和用戶的組以幫助解決所碰到的任何問題。我們不能保證總是能解決問題，相比之下，商用資料庫軟體也並不是總能夠提供解決方法。 直接與開發人員，用戶群，手冊和源程序接觸使PostgreSQL的支持比其他資料庫還要好。還有一些商業性的全面技術支持，可以給提供給那些需要的人。（參閱1.7 小節）
價格
  我們對任何用途都免費，包括商用和非商用目的。 你可以不加限制地向你的產品裡加入我們的代碼，除了那些我們在上面的版權聲明裡聲明的 BSD版權之外的內容。

### 1.14) PostgreSQL 可以處理最近各個國家夏時制的變化嗎?

PostgreSQL 8.0之前的版本是使用作業系統中的時區資料庫來處理夏時制的資訊，自 8.0 版及以後的版本 PostgreSQL 會自身含有最新的時區資訊。

## 用戶客戶端問題

### 2.1) 我們可以用什麼語言和 PostgreSQL 進行溝通？

PostgreSQL (預設情況)只安裝有 C 和內嵌式 C 的接口，其他的接口都是獨立的項目，能夠分別下載，這些接口項目獨立的好處 是他們可以有各自的發布計劃和各自獨立的開發組。

一些編程語言如 PHP 都有訪問 PostgreSQL 的接口，Perl、TCL、Python 以及很多其他語言的接口在 http://gborg.postgresql.org 網站上的 Drivers/Interfaces 小節可找到， 並且通過 Internet 很容易搜索到。

### 2.2) 有什麼工具可以把 PostgreSQL 用於 Web 頁面？

一個介紹以資料庫為後台的挺不錯的站點是：http://www.webreview.com。

對於 Web 集成，PHP 是一個極好的接口。它在 http://www.php.net/。

對於複雜的任務，很多人採用 Perl 接口和 使用 CGI.pm 的 DBD::Pg 或 mod_perl 。

### 2.3)PostgreSQL 擁有圖形用戶界面嗎？

商業用戶或是開源開發人員能找到很多的有關 PostgreSQL的GUI 圖形工具軟體，在 PostgreSQL社區文檔 有一個詳細的列表。

## 系統管理問題

### 3.1)我怎樣能把 PostgreSQL 裝在 /usr/local/pgsql 以外的地方？

在運行 configure 時加上 --prefix 選項。

### 3.2) 我如何控制來自其他電腦的連接？

預設情況下，PostgreSQL 只允許來自本機且通過 unix 域套接字或 TCP/IP 方式的連接。 你只有在修改了配置文件 postgresql.conf 中的 listen_addresses，且也在配置文件 $PGDATA/pg_hba.conf 中打開了 基於遠程電腦（ host-based ）的身份認證，並重新啟動 PostgreSQL，否則其他電腦是不能與你的 PostgreSQL 伺服器進行連接的。

### 3.3) 我怎樣調整資料庫引擎以獲得更好的性能？

有三個主要方面可以提升 PostgreSQL 的潛能。

查詢方式的變化
  這主要涉及修改查詢方式以獲取更好的性能:
  - 創建索引，包括表達式和部分索引；
  - 使用 COPY 語句代替多個 Insert 語句；
  - 將多個SQL語句組成一個事務以減少提交事務的開銷；
  - 從一個索引中提取多條記錄時使用 CLUSTER；
  - 從一個查詢結果中取出部分記錄時使用 LIMIT；
  - 使用預編譯式查詢（Prepared Query)；
  - 使用 ANALYZE 以保持精確的優化統計；
  - 定期使用 VACUUM 或 pg_autovacuum
  - 進行大量資料更改時先刪除索引（然後重建索引）
伺服器的配置
  配置文件 postgres.conf 中的很多設置都會影響性能，所有參數的列表可見：
管理員指南/資料庫伺服器運行環境/資料庫伺服器運行配置， 有關參數的解釋可見：http://www.varlena.com/varlena/GeneralBits/Tidbits/annotated_conf_e.html 和 http://www.varlena.com/varlena/GeneralBits/Tidbits/perf.html。
硬體的選擇
  電腦硬體對性能的影響可瀏覽 http://candle.pha.pa.us/main/writings/pgsql/hw_performance/index.html 和 http://www.powerpostgresql.com/PerfList/。

### 3.4)PostgreSQL 裡可以獲得什麼樣的調試特性？

PostgreSQL 有很多類似`log_*` 的伺服器配置變量可用於查詢的列印和進程統計，而這些工作對調試和性能測試很有幫助。

### 3.5) 為什麼在試圖連接時收到「Sorry, too many clients（已有太多用戶連接）」消息？

這表示你已達到預設 100 個並發(同作)後台進程數的限制，你需要通過修改 postgresql.conf 文件中的 max_connections 值來 增加 postmaster 的後台併發處理數，修改後需重新啟動 postmaster。

### 3.6)PostgreSQL 的升級過程有哪些內容 ？

PostgreSQL 開發組對每次小版本的升級主要只做了一些 Bug 修正工作，因此從 7.4.8 升級到 7.4.9 不需要 dump 和 restore，僅需要停止資料庫伺服器，安裝更新後的軟體包，然後重啟伺服器即可。

所有PostgreSQL的用戶應該在最接近（你所使用的主版本）的小改進版本發佈盡快升級。儘管每次升級可能都有一點風險，PostgreSQL的小改 進版僅僅是設計用來修正一些 Bug 的，程式碼改動較少，所以風險還是很小的。PostgreSQL社區認為一般情況下不升級的風險還是多於升級的。

主版本的升級（例如從 7.3 到 7.4）通常會修改系統表和資料表的內部格式。 這些改變一般比較複雜，因此我們不維持資料文件的向後兼容性。因此從老版本中進行資料導出（dump）/然後在新版本中進行資料導入（reload）對主版本的升級是必須的。

### 3.7)(使用 PostgreSQL )我需要使用什麼電腦硬體 ？

由於電腦硬體大多數是相容的，人們總是傾向於相信所有電腦硬體質量也是相同的。事實上不是， ECC RAM（帶奇偶校驗的記憶體），SCSI （硬碟）和優質的主機板比一些便宜貨要更加可靠且具有更好的性能。 PostgreSQL 幾乎可以運行在任何硬體上， 但如果可靠性和性能對你的系統很重要，你就需要全面的研究一下你的硬體組態了。在我們的郵件列表上也有關於 硬體配置和性價比的討論。

## 操作問題

### 4.1) 如何只選擇一個查詢結果的頭幾行？或是隨機的一行？

如果你只是要提取幾行資料，並且你在執行查詢中知道確切的行數，你可以使用 LIMIT 功能。 如果有一個索引與 ORDER BY 中的條件匹配，PostgreSQL 可能就只處理要求的頭幾條記錄， （否則將對整個查詢進行處理直到生成需要的行）。如果在執行查詢功能時不知道確切的記錄數， 可使用游標(cursor)和FETCH功能。

可使用以下方法提取一行隨機記錄的：

           SELECT  cols
          FROM tab
          ORDER BY random()
          LIMIT 1 ;

### 4.2) 如何查看表、索引、資料庫以及用戶的定義？如何查看psql裡用到的查詢指令並顯示它們？

在psql中使用 \dt 命令來顯示資料表的定義，要瞭解 psql 中的完整命令列表可使用 \? ，另外，你也可以閱讀 psql 的源代碼 文件 pgsql/src/bin/psql/describe.c，它包括為生成 psql 反斜槓命令的輸出的所有 SQL 命令。你還可以帶 -E 選項啟動 psql， 這樣它將列印出你在 psql 中所給出的命令執行時的內部實際使用的 SQL 查詢語句。PostgreSQL也提供了一個兼容 SQL的 INFORMATION SCHEMA 接口， 你可以從這裡獲取關於資料庫的資訊。

在系統中也有一些以 pg_ 打頭的系統表也描述了表的定義。

使用 psql -l 指令可以列出所有的資料庫。

也可以瀏覽一下 pgsql/src/tutorial/syscat.source 文件，它列舉了很多可從資料庫系統表中獲取資訊的SELECT語法。

### 4.3) 如何更改一個欄位的資料類型？

在8.0版本裡更改一個欄位的資料類型很容易，可使用 ALTER TABLE ALTER COLUMN TYPE 。

在以前的版本中，可以這樣做：

        BEGIN;
        ALTER TABLE tab ADD COLUMN new_col new_data_type;
        UPDATE tab SET new_col = CAST(old_col AS new_data_type);
        ALTER TABLE tab DROP COLUMN old_col;
        COMMIT;

你然後可以使用 VACUUM FULL tab 指令來使系統收回無效資料所佔用的空間。

### 4.4) 單條記錄，單個表，單個資料庫的最大限制是多少？

下面是一些限制：

> 單個資料庫最大尺寸？ | 無限制（已存在有 32TB 的資料庫）
> 單個表的最大尺寸？ | 32 TB
> 一行記錄的最大尺寸？ | 1.6 TB
> 一個欄位的最大尺寸? | 1 GB
> 一個表裡最大列數？ | 無限制
> 一個表裡最大欄位數？ | 250-1600 （與列類型有關）
> 一個表裡的最大索引數量？ | 無限制

當然，實際上沒有真正的無限制，還是要受可用磁盤空間、可用記憶體/交換區的制約。 事實上，當上述這些數值變得異常地大時，系統性能也會受很大影響。

單表的最大大小 32 TB 不需要作業系統對單個文件也需這麼大的支持。大表用多個 1 GB 的文件存儲，因此文件系統大小的限制是不重要的。

如果預設的塊大小增長到 32K ，最大的單表大小和最大列數還可以增加到四倍。

有一個限制就是不能對大小多於2000字節的列創建索引。幸運地是這樣的索引很少用到。通過對多字節列的內容進行MD5哈稀運算結果進行函數索引可對列的唯一性得到保證， 並且全文檢索允許對列中的單詞進行搜索。

### 4.5) 存儲一個典型的文本文件裡的資料需要多少磁盤空間？

一個 Postgres 資料庫（存儲一個文本文件）所佔用的空間最多可能需要相當於這個文本文件自身大小5倍的磁盤空間。

例如，假設有一個 100,000 行的文件，每行有一個整數和一個文本描述。 假設文本串的平均長度為20位元組(Byte)。文本文件佔用 2.8 MB。存放這些資料的PostgreSQL資料庫文件大約是 5.2 MB:

         24 字元組: 每行的頭（大約值）
         24 字元組節: 一個整數型欄位和一個文本型欄位
       +  4 字元組節: 頁面內指向元組的指針
       ----------------------------------------
         52 字元組每行

       PostgreSQL 資料頁的大小是 8192 位元組 (8 KB)，則：

       8192 字元組每頁
       -------------------   =  158 行/資料頁（向下取整）
         52 字元組每行

       100000 資料行
       --------------------  =  633 資料頁（向上取整）
          146 行/資料頁

       633 資料頁 * 8192 字節/頁  = 5,185,536 字節（5.2 MB）

索引不需要這麼多的額外消耗，但也確實包括被索引的資料，因此它們也可能很大。

空值 NULL 存放在位圖中，因此佔用很少的空間。

### 4.6) 為什麼我的查詢很慢？為什麼這些查詢沒有利用索引？

並非每個查詢都會自動使用索引。只有在表的大小超過一個最小值，並且查詢只會選中表中較小比例的記錄時才會採用索引。 這是因為索引掃瞄引起的隨即磁盤存取可能比直接地讀取表（順序掃瞄）更慢。

為了判斷是否使用索引，PostgreSQL 必須獲得有關表的統計值。這些統計值可以使用 VACUUM ANALYZE，或 ANALYZE 獲得。 使用統計值，優化器知道表中有多少行，就能夠更好地判斷是否利用索引。 統計值對確定優化的連接順序和連接方法也很有用。在表的內容發生變化時，應定期進行統計值的更新收集。

索引通常不用於 ORDER BY 或執行連接。對一個大表的一次順序掃瞄再做一次排序通常比索引掃瞄要快。然而，如果將 LIMIT 和 ORDER BY 結合在一起使用的話，通常將會使用索引，因為這時僅返回表中的一小部分記錄。

如果你確信PostgreSQL的優化器使用順序掃瞄是不正確的，你可以使用`SET enable_seqscan TO 'off'`指令來關閉順序掃瞄， 然後再次運行查詢，你就可以看出使用一個索引掃瞄是否確實要快一些。

當使用通配符操作，例如 LIKE 或 ~ 時，索引只能在特定的情況下使用：

- 字符串的開始部分必須是普通字符串，也就是說：
  - LIKE 模式不能以 % 打頭。
  - ~ （正則表達式）模式必須以 ^ 打頭。
- 字符串不能以匹配多個字符的模式類打頭，例如 [a-e]。
- 大小寫無關的查找，如 ILIKE 和 ~* 等不使用索引，但可以用 4.8 節描述的表達式索引。
- 在做 initdb 時必須採用預設的本地設置 C locale，因為系統不可能知道在非 C locale 情況時下一個最大字符是什麼。 在這種情況下，你可以創建一個特殊的 `text_pattern_ops` 索引來用於 LIKE 的索引。

在 8.0 之前的版本中，除非要查詢的資料類型和索引的資料類型相匹配，否則索引經常是未被用到，特別是對 int2, int8 和數值型的索引。

### 4.7) 我如何才能看到查詢優化器是怎樣評估處理我的查詢？

參考 EXPLAIN 手冊頁。

### 4.8) 我怎樣做正則表達式搜索和大小寫無關的正則表達式查找？怎樣利用索引進行大小寫無關查找？

操作符 ~ 處理正則表達式匹配，而 ~* 處理大小寫無關的正則表達式匹配。大小寫無關的 LIKE 變種成為 ILIKE。

大小寫無關的等式比較通常寫做：

        SELECT *
        FROM tab
        WHERE lower(col) = 'abc';

這樣將不會使用標準的索引。但是可以創建一個在這種情況下使用的表達式索引:

        CREATE INDEX tabindex ON tab (lower(col));

如果上述索引在創建時加入 UNIQUE 約束，雖然索引欄位自身內容可以存儲大小寫不限的內容，但如果有 UNIQUE 約束後，這些內容不能僅僅是大小寫不同（否則會造成衝突）。為了保證不發生這種情況，可以使用 CHECK 約束條件或是觸發器在錄入時進行限制。

### 4.9) 在一個查詢裡，我怎樣檢測一個欄位是否為 NULL ？我如何才能準確排序而不論某欄位是否含 NULL 值？

用 IS NULL 和 IS NOT NULL 測試這個欄位，具體方法如下：

       SELECT *
       FROM tab
       WHERE col IS NULL;

為了能對含 NULL 欄位排序，可在 ORDER BY 條件中使用 IS NULL 和 IS NOT NULL 修飾符，條件為真 true 將比條件為假 false 排在前面，下面的例子就會將含 NULL 的記錄排在結果的上面部分：

       SELECT *
       FROM tab
       ORDER BY (col IS NOT NULL)

### 4.10) 各種字符類型之間有什麼不同？

> 類型 | 內部名稱 | 說明
> --- | --- | ---
> VARCHAR(n) | varchar | 指定了最大長度，變長字符串，不足定義長度的部分不補齊
> CHAR(n) | bpchar | 定長字符串，實際資料不足定義長度時，以空格補齊
> TEXT | text | 沒有特別的上限限制（僅受行的最大長度限制）
> BYTEA | bytea | 變長字節序列（使用NULL字符也是允許的）
> "char" | char | 單個字符

在系統表和在一些錯誤資訊裡你將看到內部名稱。

上面所列的前四種類型是 "varlena"（變長）類型（也就是說，開頭的四個字節是長度，後面才是資料）。 於是實際佔用的空間比聲明的大小要多一些。 然而這些類型如定義很長時都可以被壓縮存儲，因此磁盤空間也可能比預想的要少。

VARCHAR(n) 在存儲限制了最大長度的變長字符串是最好的。 TEXT 適用於存儲最大可達 1G 左右但未定義限制長度的字符串。

CHAR(n) 最適合於存儲長度相同的字符串。 CHAR(n)會根據所給定的欄位長度以空格補足（不足的欄位內容）， 而 VARCHAR(n) 只存儲所給定的資料內容。 BYTEA 用於存儲二進制資料，尤其是包含 NULL 字節的值。這些類型具有差不多的性能。

### 4.11.1) 我怎樣創建一個序列號或是自動遞增的欄位？

PostgreSQL 支持 SERIAL 資料類型。（欄位定義為SERIAL後）將自動創建一個序列生成器，例如：

       CREATE TABLE person (
          id   SERIAL,
          name TEXT
       );

會自動轉換為以下SQL語句：

       CREATE SEQUENCE person_id_seq;
       CREATE TABLE person (
          id   INT4 NOT NULL DEFAULT nextval('person_id_seq'),
          name TEXT
       );

參考 create_sequence 手冊頁獲取關於序列生成器的更多資訊。

### 4.11.2) 我如何獲得一個插入的序列號的值？

一種方法是在插入之前先用函數 nextval() 從序列對象裡檢索出下一個 SERIAL 值，然後再用此值精確地插入。使用 4.11.1 裡的例表，可用偽碼這樣描述：

       new_id = execute("SELECT nextval('person_id_seq')");
       execute("INSERT INTO person (id, name) VALUES (new_id, 'Blaise Pascal')");

這樣還能在其他查詢中使用存放在 new_id 裡的新值（例如，作為參照 person 表的外鍵）。 注意自動創建的 SEQUENCE 對象的名稱將會是 <table>_<serialcolumn>_seq， 這裡 table 和 serialcolumn 分別是你的表的名稱和你的 SERIAL 欄位的名稱。

類似的，在 SERIAL 對象預設插入後你可以用函數 currval() 檢索剛賦值的 SERIAL 值，例如：

       execute("INSERT INTO person (name) VALUES ('Blaise Pascal')");
       new_id = execute("SELECT currval('person_id_seq')");

### 4.11.3) 同時使用 currval() 會導致和其他用戶的衝突情況嗎？

不會。currval() 返回的是你本次會話進程所賦的值而不是所有用戶的當前值。

### 4.11.4) 為什麼不在事務異常中止後重用序列號呢？為什麼在序列號欄位的取值中存在間斷呢？

為了提高併發性，序列號在需要的時候賦予正在運行的事務，並且在事務結束之前不進行鎖定， 這就會導致異常中止的事務後，序列號會出現間隔。

### 4.12) 什麼是 OID ？什麼是 CTID ？

PostgreSQL 裡創建的每一行記錄都會獲得一個唯一的 OID，除非在創建表時使用 WITHOUT OIDS 選項。 OID 創建時會自動生成一個 4位元組的整數，所有 OID 在相應 PostgreSQL 伺服器中均是唯一的。 然而，它在超過 40億時將溢出， OID 此後會出現重複。PostgreSQL 在它的內部系統表裡使用 OID 在表之間建立聯繫。

在用戶的資料表中，最好是使用 SERIAl 來代替 OID 因為 SERIAL 只要保證在單個表中的數值是唯一的就可以了，這樣它溢出的可能性就非常小了， SERIAL8 可用來保存8字元組的序列數值。

CTID 用於標識帶著資料塊（地址）和（塊內）偏移的特定的物理行。 CTID 在記錄被更改或重載後發生改變。索引資料使用它們指向物理行。

### 4.13) 為什麼我收到錯誤資訊「ERROR: Memory exhausted in AllocSetAlloc()」？

這很可能是系統的虛擬內存用光了，或者內核對某些資源有較低的限制值。在啟動 postmaster 之前試試下面的命令：

       ulimit -d 262144
       limit datasize 256m

取決於你用的 shell，上面命令只有一條能成功，但是它將把你的進程資料段限制設得比較高， 因而也許能讓查詢完成。這條命令應用於當前進程，以及所有在這條命令運行後創建的子進程。 如果你是在運行SQL客戶端時因為後台返回了太多的資料而出現問題，請在運行客戶端之前執行上述命令。

### 4.14) 我如何才能知道所運行的PostgreSQL的版本？

從 psql 裡，輸入 `SELECT version();`指令。

### 4.15) 我如何創建一個預設值是當前時間的欄位？

使用 CURRENT_TIMESTAMP：

       CREATE TABLE test (x int, modtime TIMESTAMP DEFAULT CURRENT_TIMESTAMP );

### 4.16) 我怎樣進行 outer join （外連接）？

PostgreSQL 採用標準的 SQL 語法支持外連接。這裡是兩個例子：

       SELECT *
       FROM t1 LEFT OUTER JOIN t2 ON (t1.col = t2.col);

或是

       SELECT *
       FROM t1 LEFT OUTER JOIN t2 USING (col);

這兩個等價的查詢在 t1.col 和 t2.col 上做連接，並且返回 t1 中所有未連接的行（那些在 t2 中沒有匹配的行）。 右[外]連接（RIGHT OUTER JOIN）將返回 t2 中未連接的行。 完全外連接（FULL OUTER JOIN）將返回 t1 和 t2 中未連接的行。 關鍵字 OUTER 在左[外]連接、右[外]連接和完全[外]連接中是可選的，普通連接被稱為內連接（INNER JOIN）。

### 4.17) 如何使用涉及多個資料庫的查詢？

沒有辦法查詢當前資料庫之外的資料庫。 因為PostgreSQL要加載與資料庫相關的系統目錄（系統表），因此跨資料庫的查詢如何執行是不定的。

附加增值模塊 contrib/dblink 允許採用函數調用實現跨庫查詢。當然用戶也可以同時連接到不同的資料庫執行查詢然後在客戶端合併結果。

### 4.18) 如何讓函數返回多行或多列資料？

在函數中返回資料記錄集的功能是很容易使用的，詳情參見： http://techdocs.postgresql.org/guides/SetReturningFunctions

### 4.19) 為什麼我在使用 PL/PgSQL 函數存取臨時表時會收到錯誤資訊「relation with OID ##### does not exist」？

PL/PgSQL 會緩存函數的腳本內容，由此帶來的一個不好的副作用是若一個 PL/PgSQL 函數訪問了一個臨時表，然後該表被刪除並重建了，則再次調用該函數將失敗， 因為緩存的函數內容仍然指向舊的臨時表。解決的方法是在 PL/PgSQL 中用EXECUTE 對臨時表進行訪問。這樣會保證查詢在執行前總會被重新解析。

### 4.20) 目前有哪些資料複寫(replication)方案可用？

「複寫」只是一個術語，有好幾種複寫技術可用，每種都有優點和缺點：

主/從式複寫方式是允許一個主伺服器接受讀/寫的申請，而多個從伺服器只能接受讀/SELECT查詢的申請， 目前最流行且免費的主/從PostgreSQL複寫方案是 Slony-I 。

多個主伺服器的複寫方式允許將讀/寫的申請發送給多台的主機，這種方式由於需要在多台伺服器之間同步資料變動 可能會帶來較嚴重的性能損失，Pgcluster 是目前這種方案中最好的，並且還可以免費下載。

也有一些商業需付費和基於硬體的資料複寫方案，支持上述各種複寫模型。

### 4.21) 為何查詢結果顯示的表名或欄名與我的查詢語句中的不同？為何大寫狀態不能保留？

最常見的原因是在創建表時對表名或是欄名使用了雙引號( ' ' )，當使用了雙引號後，表名或欄名（稱為標識符）存儲時是區分 大小寫的， 這意謂著你在查詢時表名或欄名也應使用雙引號，一些工具軟體，像 pgAdmin 會在發出創建表的指令時自動地在每個標識符上加雙引號。 因此，為了標識符的統一，你應該：

- 在創建表時避免將標識符使用雙引號引起來。
- 在標識符中只使用小寫字母。
- （為了與已存在的標識符相同）在查詢中使用雙引號將標識符引起來。