惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 叶小钗
爱范儿
爱范儿
WordPress大学
WordPress大学
Last Week in AI
Last Week in AI
博客园 - 聂微东
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 三生石上(FineUI控件)
T
Tailwind CSS Blog
博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 司徒正美
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Cloudflare Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
宝玉的分享
宝玉的分享
罗磊的独立博客
Jina AI
Jina AI

Nic Lin's Blog

謝明真 - 高效領導力的課後筆記 NFT 開發實戰!基礎智能合約入門 (3) NFT 開發實戰!基礎智能合約入門 (2) NFT 開發實戰!基礎智能合約入門 (1) 如何自我檢測 log4j CVE 漏洞 Rails 如何在資料寫入時記錄來源 IP 位置 如何經營工程師 Youtube 頻道 - Part 8 營收篇 如何經營工程師 Youtube 頻道 - Part 7 酸民文化篇 如何經營工程師 Youtube 頻道 - Part 5 設備器材篇 如何經營工程師 Youtube 頻道 - Part 4 後製剪輯篇 如何經營工程師 Youtube 頻道 - Part 3 文案企劃篇 如何經營工程師 Youtube 頻道 - Part 2 設備器材篇 如何經營工程師 Youtube 頻道 - Part 1 制訂頻道方向篇 如何經營工程師 Youtube 頻道 - Part 0 Rails 中避免 race condition 的最佳實踐(二) Rails 中避免 race condition 的最佳實踐(一) 10 分鐘整合 google sheet 做自動化開發功能週報 經營 Side Project 300 天所帶來的收穫及挑戰 我的 Youtube 影片製作流程 API 設計時必須注意的 HTTP header 底線問題 如何提升你的程式可讀性之實務技巧(三) 如何提升你的程式可讀性之實務技巧(二) 如何提升你的程式可讀性之實務技巧(一) Ruby 中使用 freeze 優化效能的時機 避免 React 中的 useEffect 無限 render 在 Rails 內輕量使用 Vue Component 的最佳實踐 如何在區域網路用 Docker 架設有 SSL 的 Gitlab 從被問到問人,那些我常問的面試問題 [Rails] 如何漂亮寫出可維護的 query (Maintainable Rails Query) 在已知長度情況下優化 slice 的性能
[Rails] 如何快速的對大資料量建立索引,避免 Downtime
Nic Lin · 2018-06-15 · via Nic Lin's Blog

Postgres 在建立索引時,會阻塞 DML 也就是 lock 整個 table 的寫入(讀取則不影響),所以當需要對大資料量的 Table 打 index 時,會造成有 Downtime 時間,這在 Production 這種高並發的環境下是不適合的。

並發計算建立 index

Postgres 在建立索引時有提供 CONCURRENTLY 的選項可以設定(並發計算),這樣一來就不會影響 table 的寫入行為(INSERT, UPDATE, DELETE)

可以同時處理一般的寫入行為,也可以打 index, 不過是生成時間會再慢一些,但至少沒有停機時間。

在 Rails 4 之後可以直接加入 algorithm: :concurrently 在你的 migration 檔案內

例如:

class AddIndexToUsers < ActiveRecord::Migration
  disable_ddl_transaction!

  def change
    add_index :users, :alive, algorithm: :concurrently
  end
end

不過這邊要注意的是, disable_ddl_transaction! 與 algorithm: :concurrently 是一組的,必須一起使用。

如果你有其他的 migrate 要做,建議分開。

為什麼要用 disable_ddl_transaction! ?

因為在 Rails 的 migration 中預設每個執行都會包一個 transaction ,如果有失敗的情況就會整個 Rollback,但如果要使用 Postgres 當中的 Concurrently 去建立 index 的話,必須要在 transaction 之外 (concurrent indexes must be created outside a transaction.)

副作用

一般 CREATE INDEX 情況下,只會掃一次表,但如果使用這個並發計算參數時,則會引發 Database 掃兩次表,並且等待所有潛在會讀到該索引的事務結束,這樣一來會增加 CPU + I/O 的負擔,不過拿這個負擔來換 Downtime 想必是划算的。

失敗情況

使用 concurrently 參數時,有可能遇到創建索引失敗的狀況,比方說建立 uniqu 索引結果發現數據重複了,此時 Table 上會存在索引,這是因為帶 concurrently 參數的指令發出後,會馬上在 Log 裡面插一個 index 記錄進去,又因為這個索引建立失敗了,會被標記一個 INVALID 的狀態

"idx" btree (col) INVALID

參考來源