# REINDEX

REINDEX — 重建索引

### 語法

```
REINDEX [ ( VERBOSE ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } name
```

### 說明

REINDEX 使用索引資料表中所儲存的資料重建索引，替換索引舊的版本。有幾種情況可以使用 REINDEX：

* 索引損壞，不再包含有效的資料。雖然理論上這種情況永遠不會發生，但實際上索引會因程式錯誤或硬體故障而損壞。REINDEX 提供了一種恢復的方法。
* 索引變得「臃腫」，即它包含許多空或幾乎空的頁面。在某些不常見的存取模式下，PostgreSQL 中 的 B-tree 索引會發生這種情況。REINDEX 提供了一種透過寫入無死頁的索引新版本來減少索引空間消耗的方法。有關更多訊息，請參閱[第 24.2 節](https://docs.postgresql.tw/11/server-administration/routine-database-maintenance-tasks/routine-reindexing)。
* 您變更了索引的儲存參數（例如 fillfactor），並希望確保變更能完全生效。
* 使用 CONCURRENTLY 選項的索引建構失敗，留下「無效」的索引。 這些索引沒用，但使用 REINDEX 重建它們會很方便。請注意，REINDEX 將不執行同步建構。要在不干擾線上查詢的情況下建構索引，您應該刪除索引並重新發出 CREATE INDEX CONCURRENTLY 指令。

### 參數

`INDEX`

重新建立指定的索引。

`TABLE`

重新建立指定資料表的所有索引。如果資料表具有額外的「TOAST」資料表，那麼也會重新編制索引。

`SCHEMA`

重新建立指定綱要的所有索引。如果此綱要的資料表具有額外的「TOAST」資料表，那麼也會重新編制索引。還會處理共享系統目錄上的索引。這種形式的 REINDEX 不能在交易事務區塊中執行。

`DATABASE`

重新建立目前資料庫中的所有索引。還會處理共享系統目錄上的索引。這種形式的 REINDEX 不能在交易事務區塊中執行。

`SYSTEM`

重新建立目前資料庫中系統目錄的所有索引。包含共享系統目錄的索引。但不處理使用者資料表的索引。這種形式的 REINDEX 不能在交易事務區塊中執行。

*`name`*

要重新編制索引的特定索引，資料表或資料庫的名稱。索引和資料表名稱可以是加上綱要名稱的。目前，REINDEX DATABASE 和 REINDEX SYSTEM 只能重新索引目前資料庫，因此它們的參數必須符合目前資料庫的名稱。

`VERBOSE`

在重新索引每個索引時輸出進度報告。

### 注意

如果您懷疑使用者資料表上的索引損壞，您可以使用 REINDEX INDEX 或 REINDEX TABLE 簡單地重建該索引或資料表上的所有索引。

如果您需要從系統資料表上的索引損壞中恢復，則事情會比較困難。在這種情況下，系統沒有使用到任何可疑索引很重要。（實際上，在這種情況下，由於依賴於損壞的索引，您可能會發現伺服器程序在啟動時立即終止。）要安全恢復，必須使用 -P 選項啟動伺服器，這樣可以防止伺服器程序使用索引進行系統目錄查詢。

一種方法是關閉伺服器並啟動單一使用者模式的 PostgreSQL 伺服器，其命令列中包含 -P 選項。然後，可以發出 REINDEX DATABASE，REINDEX SYSTEM，REINDEX TABLE 或 REINDEX INDEX，具體取決於您需要重建的程度。如有疑問，請使用 REINDEX SYSTEM 選擇資料庫中所有系統索引的重建。然後退出單一使用者模式伺服器連線再重新啟動一般模式伺服器。有關如何與單一使用者模式伺服器界面交互的更多訊息，請參閱 [postgres](https://docs.postgresql.tw/11/reference/server-applications/postgres) 參考頁面。

或者，可以在其命令列選項中包含 -P 的情況下啟動一般模式的伺服器連線。執行此操作的方法因用戶端而異，但在所有基於 libpq 的客戶端中，可以在啟動用戶端之前將 PGOPTIONS 環境變數設定為 -P。請注意，雖然此方法不需要鎖定其他用戶端，但在修復完成之前阻止其他用戶連線到損壞的資料庫仍然是明智之舉。

REINDEX 類似於索引的刪除和重新建立，因為索引內容是從頭開始建立的。但是，鎖定考慮情況是相當不同的。REINDEX 鎖定寫入但不讀取索引的父資料表。它還對正在處理的特定索引進行獨占鎖定，這將阻止嘗試使用該索引的讀取。相反，DROP INDEX 會暫時對父資料表進行獨占鎖定，從而阻止寫入和讀取。隨後的 CREATE INDEX 鎖定寫入但不讀取；由於索引不在那裡，沒有讀取會嘗試使用它，這意味著沒有阻塞但是讀取可能會被強制進入昂貴的循序掃描。

重新索引單個索引或資料表需要成為該索引或資料表的擁有者。重新索引資料庫需要成為資料庫的擁有者（請注意，擁有者因此可以重建其他使用者擁有的資料表索引）。當然，超級使用者總是可以重新索引任何東西。

### 範例

重建單個索引：

```
REINDEX INDEX my_index;
```

重建資料表 my\_table 上的所有索引：

```
REINDEX TABLE my_table;
```

重建特定資料庫中的所有索引，而不必信任系統索引是否有效：

```
$ export PGOPTIONS="-P"
$ psql broken_db
...
broken_db=> REINDEX DATABASE broken_db;
broken_db=> \q
```

### 相容性

SQL 標準中沒有 REINDEX 指令。
