OpenAI 如何將 PostgreSQL 擴展到支撐 8 億名使用者

2026年2月7日

💎 加入 E+ 成長計畫 與超過 950+ 位工程師一同在社群成長,並獲得更多深度的軟體前後端學習資源

OpenAI 最近發表了《Scaling PostgreSQL to power 800 million ChatGPT users》一文。這篇文章談 OpenAI 的核心產品 ChatGPT 背後所使用的資料庫系統 PostgreSQL。

在文章當中,他們分享如何擴展 PostgreSQL 來支撐 ChatGPT 超過 8 億的使用者,這是個非常驚人的數字。在這支影片當中,我們會跟大家來聊聊 ChatGPT 它實際跟 PostgreSQL 之間的關係,以及在 ChatGPT 的流量逐漸大起來後,遇到哪些擴展上面的問題。最後當然也會來聊在文章當中分享的關鍵精華,是 OpenAI 的團隊如何解決這些遇到的問題。

OpenAI 與 Postgres

首先,ChatGPT 與 Postgres 之間有些什麼樣的關係呢?相信多數人在使用 ChatGPT 這個工具的時候,是要使用它核心的生成式 AI 的功能,但事實上作為一個應用產品,除了提供這個核心的生成式 AI 的功能之外,它其實也會需要存各式各樣的資料,這是為什麼 ChatGPT 它會需要 Postgres 的原因。

舉例來講,當今天使用者註冊 ChatGPT,它會需要存使用者相關的資料,這樣下一次使用者重新登入或者使用的時候,產品才能夠去調出使用者相關的資料。這些資料可能也包含使用者有的設定,例如說我們在使用 ChatGPT 的時候會去設定系統提示詞 System Prompt。相信多數的使用者不會想要這次設完系統提示詞,下一次再回來之後這個系統提示詞就要重新再設一次。那假設要做到這樣的話,ChatGPT 勢必背後需要有一個資料庫來存系統提示詞。

除此之外,大家在用 ChatGPT 的時候相信也會希望能夠留存過去的聊天歷史記錄,而這個時候也會需要有一個資料庫來去存這些記錄。在文章中有提到 ChatGPT 這個產品其實有用各式不同的資料庫,例如說有用 Redis 或者有用其他的 NoSQL 資料庫,但是他們最核心使用的資料庫是 Postgres。

而隨著 ChatGPT 的使用者人數越來越多,到了 2026 年這篇文章發表的時候,短短三年多 ChatGPT 的使用人數已經超過了 8 億。在文章中有提到因為這個使用者的人數大量的增加,他們對於 Postgres 的用量的需求也增加了超過 10 倍。而當今天使用量增加的時候,就很可能會遇到原本的機器已經不夠應付當前的需求這種非常奢華的困擾。

在這種狀況下,通常會有兩種做法來解決。第一個是所謂的向上擴展,或者大家很常聽到的垂直擴展。原本的機器不夠應付,我們就把機器升級成一個規格更好更頂的機器。不過相信大家可能會問,我們要把規格提高總是會有一個上限,不可能無限地去增加機器的規格。所以這時候會有另一種做法叫向外擴展,或者大家很常聽到的水平擴展。這個做法是今天假設我原本的機器已經不夠應付了,我們可以去增加更多台機器。

事實上 OpenAI 的團隊他們兩個做法都用上了。雖然在這篇文章當中沒有寫,但是同一個作者之前在另一個相關的演講中有提到,OpenAI 的團隊基本上是用 Azure 上最頂規的機器,所以算是向上擴展已經做到了一個極致。除了去使用最頂規的機器之外,他們同時也做了向外擴展。

具體來講有做兩件事,第一件事情是分片 (Sharding),另一件事情是複寫 (Replication)。

所謂的分片 Sharding 是去把資料庫拆成不同的分片 (不同的 Shard),我們會分別使用不同的機器實例。假設今天對於資料庫的寫入的請求 A 與 C 的請求,我可以寫到第一個分片;對於 B 跟 D 的請求,我可以去寫到第二個分片當中。

所以假設今天我們使用的機器每秒能夠去處理 1000 個寫的請求,當我們去切成多個不同的資料庫實例的時候,就能夠同時去支應更多的寫入的請求。

除了分片之外,複寫 (Replication) 也是一個很常會使用到的向外擴展的方式。所謂的複寫是我們有一個主要的資料庫 (在實務上可能會有多個,不過簡化來理解的話有一個主要的資料庫),然後其他的從屬的資料庫,是把主要的資料庫複製過去一份。假設有查詢相關的請求,就不需要發向主資料庫,而是可以由已經複製好相關資料的從資料庫來去處理。

在有了以上的基礎的概念之後,往下我們就來談一下在文章當中 OpenAI 的團隊實際分享 ChatGPT 的流量大起來後,他們遇到哪些擴展的挑戰。

ChatGPT 流量大起來後遇到的擴展挑戰

在 OpenAI 他們的整體的架構來講,他們是只有一個主資料庫負責所有寫入的請求,與此同時他們有將近 50 個不同的複本、不同的從資料庫來處理讀取相關的請求。之所以會這樣設計,有一個很核心的關鍵是 ChatGPT 以及 OpenAI 有的這些 API 在遇到的讀寫比例來看是讀取偏重,對於讀的需求比較大一點。在這種狀況下,採用單一個主資料庫,在全世界不同的區域有不同的複本,就能夠非常好地去應對大量的讀取相關的請求。

但這個時候就有一個問題來了,雖然說對於 ChatGPT 的使用場景來說讀取的需求比較大,但是因為他們全球還是有超過 8 億個使用者,所以即使寫的比例沒有讀的比例那麼多,量總體來講還是非常大的。在這種狀況下,Postgres 本身的設計上面對於要處理比較大量的寫入請求效率會比較低一點。

在文章當中作者有提到另一篇是由 CMU 的資料庫教授 Andy Pavlo 跟作者協作的另一篇文章,來談 Postgres 的 Multiversion Concurrency Control MVCC 這個設計導致了這種大量寫入請求效率比較低的狀況。在這邊我們就不展開來談,推薦讀者可以去實際讀這篇文章了解細節。

當今天 Postgres 在處理大量寫入請求效率比較低的同時,OpenAI 的整體的架構當中又只有一個負責處理寫入請求的主資料庫,這個時候假如主資料庫過載就很容易導致事故。這邊我們放了在文章當中實際有分享出來的一張圖,在這張圖當中就有談到可能會因為快取沒有命中,或者說有一些查詢比較昂貴,或者 ChatGPT 有某個新功能上線有大量的使用者使用的時候會有增加非常大量的寫入的請求。

這些不同的狀況可能會導致負責處理寫入請求的主資料庫有過載的狀況,而當這個負責處理寫入請求的主資料庫過載就可能會導致一些請求變得比較慢,或者甚至會超時。這時候可能就會有更多人重試,所以發送了更多的寫入請求,造成一個惡性的循環。原本因為已經有太多寫入請求導致過載,這時候來了更多的寫入請求就導致整個主資料庫崩潰掉,因而造成事故。

不過這個時候相信大家可能會問,我們前面有談到 OpenAI 的團隊在做向外擴展的時候有使用分片,而且分片是一個能夠有效去擴展寫入請求的方式,那麼為什麼他們不在這個主資料庫去做分片呢?

這邊最主要有兩點。第一點是,如我們前面有談的,事實上 OpenAI 的團隊在處理寫入請求的時候是有做分片的,但是不是做在這個 Postgres 的主資料庫上面,待會我們會詳細地談他們怎麼做。但是這還是沒有回答到為什麼不在這個主資料庫做分片,因為最關鍵的點是 ChatGPT 這個產品以及相關的 API 的成長速度實在太快了。所以當一下規模到了這麼大的程度,要去做分片會是非常耗時的,因為一次要做分片可能會動到好幾百個不同的應用端的介面。所以假設要非常安全、非常完整的去執行主資料庫的分片,可能會需要花好幾個月,甚至一兩年的時間才能做到。

所以在文章中有提到,他們其實是有考慮為主資料庫做分片,但是不是現在立即做,因為現在也沒有辦法馬上做完。假如短期沒有辦法完成這件事,核心的關注點就會是在不做主資料庫分片的狀況之下,要如何去承接越來越大的請求,要如何去做好擴展這件事。

降低對主資料庫的請求

接著讓我們一起來看看 OpenAI 的團隊是如何解決這些問題的。我們先來看到第一個挑戰。還記得前面有談到 OpenAI 的 Postgres 的架構是由單一的主要資料庫作為寫入使用。由於要去分片這個主資料庫會需要花非常多的時間,所以他們在短期並沒有考慮去做分片。因此這個單一的主資料庫本身是會有一個擴展的瓶頸,因為它不管規格怎麼升、CPU 再升到某一個程度,還是會有硬體的極限所在。這個時候,假設有一個大量的高峰的寫入,就很可能導致這個主節點過載,影響到 ChatGPT 跟 OpenAI 的其他 API 的服務。

大家可以稍微暫停一下影片思考一下,假設是你遇到了這樣現實的技術的限制,你會如何來解決這個問題?

在文章當中,OpenAI 的團隊分享了三個主要的點。假設今天請求的量變大,主資料庫可能會撐不住,那麼我們可以做的第一個做法就是去減少請求量。而具體的做法,就如前面有談到的,這個主資料庫作為寫入,而其他讀取相關的請求是會透過複本複寫的方式分到其他的從屬資料庫。所以今天我們可以把所有讀取相關的請求盡可能的由複本的資料庫處理,不要讓讀取相關的請求進到主資料庫,這樣就能大量的減少主資料庫會需要處理的請求。

而第二個他們做的事情是,雖然這個 Postgres 主資料庫本身要做分片會需要花好幾個月,甚至數年的時間,所以他們短期不考慮,但是可能會有一些新的寫入需求是能夠做分片的。那這個時候,這些新的寫入需求就不要進到這個主資料庫,而是進到別的資料庫。具體來說,OpenAI 他們使用微軟的 Cosmos DB 來處理這些能夠做分片的寫入。這邊大家可能比較容易搞混,所以特別強調:他們的主資料庫 Postgres 的這個主資料庫本身沒有做分片,能夠做分片的寫入是搬到另一個資料庫 Cosmos DB 去處理。

除了前面這兩點,OpenAI 的團隊還有做的一件事情是延遲寫入 Lazy Write。所謂的延遲寫入是指盡量避免在某一個尖峰的當下把所有的寫入都塞進去,因為假設真的去做分析的話,可能某一些部分的寫入並不是真的需要這麼即時的寫入。那這時候可以先把它們放一旁,先處理那些真正需要去即時寫入的請求,然後等到這些請求都處理完、高峰逐漸地緩下來之後,再去處理那些即時性需求沒有那麼高的寫入。透過這些方法,就能夠讓主資料庫要去處理的請求不會這麼多,也不會這麼密集。

查詢最佳化

接著我們來談第二個他們遇到的實務上的問題。在他們的 Postgres 系統當中,會有一些成本比較高的查詢,而這些查詢當流量大起來的時候,就會大量的消耗 CPU,進而去拖慢 ChatGPT 跟 API 的請求。遇到這種狀況,你在實務上可能會怎麼處理呢?

相信大家應該都會想到,既然查詢可能會有所謂的慢查詢或者昂貴的查詢,那我們就來做查詢的最佳化解決這件事。具體來說,他們有提到幾個他們最佳化的過程中去特別著重的點。第一個點是減少慢查詢,第二個是去特別檢視查詢的語句,最後呢,是去清理一些閒置的查詢。

首先第一個減少慢查詢這件事,在文章當中有特別強調要盡可能的去避免一些不應該出現在 OLTP 系統會出現的查詢。現在業界通常會把資料庫的系統去區分 OLTP 跟另一個 OLAP 這兩個不同類型的系統。OLTP 的系統的特性就是會專注在處理交易型的任務,所以去處理那些單次範圍比較小的寫入跟查詢。而另一種可能是要去做分析相關的,則會使用 OLAP 來處理。而這個 OLAP 就是會去處理這種需要大範圍的資料的查詢跟聚合或者篩選等等的操作。

在實務上,如果資料的系統逐漸大起來的話,沒有去區分這兩種系統,很可能會造成的問題是,今天應用程式端的後端工程師可能會需要去跟資料分析師還有資料科學家說:「可不可以請你們稍微暫停一下你們手邊的工作?因為你們去做分析而使用的那些查詢正在拖慢我們的系統。」剛剛上面描述的這種情境,就是沒有把處理事務型交易型的系統跟處理分析型的系統拆開會導致的結果。假設今天整體的流量比較小,這倒是還好,不太真的會有這樣的問題發生。但是資料系統一大起來,就很可能會有這樣的狀況出現。

在這篇文章當中有提到,他們實際去檢視 Postgres 系統會處理的查詢,竟然發現有一些查詢是會同時去 join 12 張不同的表,這種不應該出現在 OLTP 系統中該有的查詢。所以他們就辨別出這些查詢,然後把這些大範圍複雜的查詢給處理掉。

第二個,文章中特別有提到不要過度的依賴 ORM。所謂的 ORM 就是一個可以讓開發者可以去寫類似於應用端的邏輯,然後透過 ORM 的工具去轉成 SQL 的語句。但是往往有時候 ORM 在使用的時候,他們去轉出來的 SQL 語句並不是最佳化的。又或者說,像我們過去有寫過一篇文章在談所謂的 N+1 問題,也是很常在使用 ORM 的時候會出現的。所以在文章中作者有特別提到,使用 ORM 的同時也需要真的去檢視 ORM 背後產出的 SQL 的語句,不要直接全盤的接受,因為轉換出來的結果很有可能是能夠進一步去最佳化的。

最後,OpenAI 團隊在做查詢最佳化的具體方法當中,也包含去清理閒置的查詢。而他們的做法是使用 Postgres 有的這個 Idle in Transaction Session Timeout,然後去掃除那些已經閒置或者阻塞在那邊很久的查詢,然後把它們自動的清理掉。透過上面的這三種方式,就讓整體的查詢變得是更佳的,也對於資料庫的系統的負擔會比較小一點。

避免單點故障

接著第三個他們遇到的實務問題是,在他們的架構之下,因為是單一主資料庫負責寫入,然後有接近 50 個從屬的資料庫負責讀取相關的請求。在這個狀況下,假設他們的複本資料庫掛掉,還有其他的複本資料庫可以用,所以只要把流量導去那邊就可以。但是假設主資料庫掛掉的話,因為只有單一個主資料庫,那這個時候該怎麼辦呢?

一樣推薦大家可以稍微暫停一下,想一想你會怎麼做。

OpenAI 團隊具體的做法是,有這個主資料庫的同時,有另一個熱備份 Hot Standby 在旁邊。他們開啟了微軟 Azure 上面的高可用模式。換句話說,除了主資料庫本身之外,有另一個並沒有立即在使用的資料庫,但是它會同步所有主資料庫有的這些資料。所以當今天主資料庫假設一倒,這個熱備份的資料庫就能夠馬上頂上去,然後讓整體的服務仍是可用的。

但這件事情概念上講起來好像很簡單,但是實務上其實有非常多需要去克服的點。因為第一個,光是去能夠辨別主資料庫真的掛掉這件事,就是一個相當有技術挑戰的事。以及主資料庫假設真的倒了,這個熱備份去替代的同時,也不單單只是去替代它,因為所有的複本資料庫就會需要重新連線到這個原本是熱備份的資料庫。而在這整個流程當中,有非常多可能會出錯的地方。

不過這邊 OpenAI 的團隊有特別把功勞歸功於微軟的 Azure 團隊。他們在文章中有提到,這一切能夠真的很順的做到,是 Azure 團隊他們花了非常多的功夫去處理。不過回過頭來,假設你也是要使用雲端服務商所提供的資料庫服務做這種熱備份,也不是完全沒有成本的。還記得我們前面有談到 OpenAI 他們基本上在主資料庫上把向上擴展做到了極致,用了 Azure 最頂規可以使用的機器。所以換句話說,他們同時必須要再租另一台同樣最頂規的機器來作為熱備份。那這個其實不是一個便宜的金額,所以也不是完全沒有成本的。

負載隔離

再往下第四點,在實務上的時候,他們經常有遇到一些請求可能會去吃掉比較多 Postgres 的資源,導致其他的業務因此變慢。舉例來說,有些新功能上線的時候,在測試環境可能因為流量不夠大,所以沒有辦法發現是效率不佳的查詢。那這時候,這些新的功能上線,同時有大量的使用者使用去消耗 Postgres 的 CPU,就很可能會導致其他重要的功能因此變慢。

遇到這種狀況,大家覺得可以怎麼去處理呢?

OpenAI 團隊具體的做法是把負載隔離。他們透過把從屬資料庫分出不同的實例,然後把某些特定的從屬資料庫實例會分配給那些高優先度的相關的請求。這樣的做法就會讓假設今天真的某一個比較慢的查詢在新功能上線的時候被曝露出來,不會影響到那些優先度高的請求。

因為這些優先度高的請求,他們有自己專屬的資料庫實例來處理。所以假設這些比較慢、比較沒有效率的查詢上線了,會影響的也只會是那些優先度比較低的相關的請求。透過這種隔離的方式,就能夠確保最重要的東西,即使在系統中有其他部分出問題了,也不會被影響到。

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們