您好,歡迎來電子發(fā)燒友網! ,新用戶?[免費注冊]

您的位置:電子發(fā)燒友網>源碼下載>數值算法/人工智能>

Uber為什么從Postgres遷移到MySQL

大?。?/span>0.6 MB 人氣: 2017-09-30 需要積分:0

  導論

  Uber的早期架構由一個單體后端應用程序構成,該應用由Python編寫,Python使用Postgres以實現數據持久化。自那時起,Uber架構已發(fā)生巨變,逐步轉化為微服務模式和新的數據平臺。特別是在之前一些使用Postgres的案例中,現在則改用Schemaless(一個基于MySQL的全新數據庫分片)。本文將探索Postgres的缺陷,解釋遷移到MySQL的基礎上構建Schemaless和其它后端服務的原因。

  Postgres的架構

  Postgres有很多局限性:

  寫入架構低效數據復制低效表損壞的問題糟糕的從庫MVCC支持新版本更新難度升級

  下文將分析Postgres的表表示法和磁盤上的索引數據,重點對比MySQL通過其InnoDB存儲引擎呈現相同數據的方法,以探索上述缺陷。注意:本文涉及的分析主要基于舊版Postgres 9.2系列。 眾所周知,本文論述的內部架構在新發(fā)布的Postgres中沒有太大變更。事實上,至少自Postgres 8.3的發(fā)布開始(距今近十年),Postgres 9.2中磁盤上表示法的基礎設計就一直沒有做出顯著調整。

  磁盤上的數據格式

  關系數據庫必須執(zhí)行下列關鍵任務:

  支持插入/更新/刪除功能支持schema變更功能實現一個多版本并發(fā)控制(MVCC)機制,促使不同的連接對其所處理的數據生成一致性的事務視圖

  思考其所有特性如何協同運作是設計數據庫在磁盤上呈現數據的基礎。

  Postgres的一項核心設計是行數據固定。該固定行在Postgres用語中又名“元組(tuple)”。在Postgres中,元組又通過ctid獲得唯一標識。從概念上講,ctid代表元組在磁盤上的位置(例如物理磁盤偏移)。多個ctid可能能夠描述一個單行(例如多個行版本為了MVCC的目的而存在時,或是舊版本行未經autovacuum進程回收時)。一組元組的組織集合構成表,表本身包含索引,索引經組合構成數據結構(通常是B-tree結構),從而將索引字段映射到ctid的有效載荷。

  通常情況下,這些ctid是面向用戶透明的,但了解其運行方式有助于理解Postgres表在磁盤上的表架構。若要查看行的當前ctid,則可向WHERE子句中的欄目列表中添加“ctid”:

  uber@[local] uber=》 SELECTctid, * FROM my_table LIMIT 1; -[ RECORD1]--------+------------------------------ctid | (0,1) 。。.other fields here.。。

  為求布局細節(jié),先以一個簡單的用戶表為例。Uber針對每個用戶設置了自動遞增的用戶ID主鍵、用戶姓名和出生年份。同時Uber還設置了一個基于用戶全名(包括名和姓)的復合二級索引,和另一個基于用戶出生年份的二級索引。用以創(chuàng)建該表的DDL如下:

  CREATETABLEusers ( id SERIAL, firstTEXT, lastTEXT, birth_year INTEGER, PRIMARYKEY(id) );CREATEINDEX ix_users_first_last ONusers (first, last);CREATEINDEX ix_users_birth_year ONusers (birth_year);

  注意該定義中的三個索引:主鍵索引和兩個二級索引。

  為求例證,將以下面的表格數據展開論述,表中數據均由歷史上頗具影響力的數學家構成:

  id

  first

  last

  birth_year

  1 Blaise Pascal 1623

  2 Gottfried Leibniz 1646

  3 Emmy Noether 1882

  4 Muhammad al-Khwārizmī 780

  5 Alan Turing 1912

  6 Srinivasa Ramanujan 1887

  7 Ada Lovelace 1815

  8 Henri Poincaré 1854

  如前所述,表中每一行隱含一個唯一且不公開的ctid。因此,表的內部表示如下:

  ctid

  id

  first

  last

  birth_year

  A 1 Blaise Pascal 1623

  B 2 Gottfried Leibniz 1646

  C 3 Emmy Noether 1882

  D 4 Muhammad al-Khwārizmī 780

  E 5 Alan Turing 1912

  F 6 Srinivasa Ramanujan 1887

  G 7 Ada Lovelace 1815

  H 8 Henri Poincaré 1854

  設置主鍵索引(映射ID到ctid):

  id

  cti

  1 A

  2 B

  3 C

  4 D

  5 E

  6 F

  7 G

  8 H

  B-tree結構的設置基于id字段,且其每個節(jié)點都保存ctid值。在這個案例中需要注意的是,由于使用自動遞增id,B-tree中的字段順序有時會和表中順序相同,但是也不一定如此。

  二級索引彼此都很相似;主要差異在于字段存儲順序,而字段在B-tree中必須以字典順序排布。(first,last)索引從名開始按字母表順序自上而下排列。

  first

  last

  ctid

  Ada Lovelace G

  Alan Turing E

  Blaise Pascal A

  Emmy Noether C

  Gottfried Leibniz B

  Henri Poincaré H

  Muhammad al-Khwārizmī D

  Srinivasa Ramanujan F

  同樣,birth_year(出生年份)聚集索引以升序排列:

  birth_year

  ctid

  780 D

  1623 A

  1646 B

  1815 G

  1854 H

  1887 F

  1882 C

  1912 E

  綜上所述,不同于自動遞增主鍵的案例,在上面的情境下,各個二級索引中的ctid字段都不是按字母表順序升序排布的。

  假設需要更新一條表記錄,比如將al-Khwārizmī的出生年份字段更新為另一個預估值770CE。如前所述,行元組是固定的,因此,為了更新記錄,需要向表中添加一個新元組。該新元組有一個新的非公開ctid,稱之為I。Postgres需要能夠區(qū)分I上的新元組和D上的舊元組。在內部,Postgres將一個版本字段和指向前一個元組(如果有的話)的指針存于各個元組。據此,表的新結構如下:

  ctid

  prev

  id

  first

  last

  birth_year

  A null 1 Blaise Pascal 1623

  B null 2 Gottfried Leibniz 1646

  C null 3 Emmy Noether 1882

  D null 4 Muhammad al-Khwārizmī 780

  E null 5 Alan Turing 1912

  F null 6 Srinivasa Ramanujan 1887

  G null 7 Ada Lovelace 1815

  H null 8 Henri Poincaré 1854

  I D 4 Muhammad al-Khwārizmī 770

  只要al-Khwārizmī存在兩個行版本,則索引必須包含這兩個行的條目。為求簡潔,Uber此處刪除了主鍵索引,只顯示二級索引:

  first

  last

  ctid

  Ada Lovelace G

  Alan Turing E

  Blaise Pascal A

  Emmy Noether C

  Gottfried Leibniz B

  Henri Poincaré H

  Muhammad al-Khwārizmī D

  Muhammad al-Khwārizmī I

  Srinivasa Ramanujan F

  birth_year

  ctid

  770 I

  780 D

  1623 A

  1646 B

  1815 G

  1854 H

  1887 F

  1882 C

  1912 E

  此處將舊版顯示為紅色,新版為綠色。在內部,Postgre通過另一個字段保存行版本,以判定哪一個是最新元組。該新增字段幫助數據庫決定讓哪一個行元組服務于一個事務,該事務可能不被允許查看最新行版本。

  Uber為什么從Postgres遷移到MySQL

  Postgres下,主索引和二級索引都直指磁盤上的元組偏移。若一個元組的位置發(fā)生改變,則必須更新全部索引。

非常好我支持^.^

(1) 100%

不好我反對

(0) 0%

      發(fā)表評論

      用戶評論
      評價:好評中評差評

      發(fā)表評論,獲取積分! 請遵守相關規(guī)定!

      ?