摘要: 背景 資料移轉是資料庫營運中一個很常見的情境。資料移轉分為全量和增量。為了追求速度,通常我們會採用並發的方式對資料進行全量遷移。在全量匯出資料時,通常都會選擇做到記錄級的並發,因此通常會涉及到對需要匯出的某個表(集合)按照並發度進行切分(分區)的過程。 背景
資料移轉是資料庫營運中一個很常見的情境。資料移轉分為全量和增量。為了追求速度,通常我們會採用並發的方式對資料進行全量遷移。在全量匯出資料時,通常都會選擇做到記錄級的並發,因此通常會涉及到對需要匯出的某個表(集合)按照並發度進行切分(分區)的過程。現有常用做法是通過若干個skip加limit來找到一些分區點,然後就可以並發同時匯出多個分區。事實上MongoDB還有一個SplitVector命令特別適合用來做集合的分區。本文將介紹一下如何利用這個命令來對集合做分區,實現並發資料移轉。 命令簡介
SplitVector命令原是在sharding中chunk分裂時需要用的一個內部命令,是mongos在準備分裂某個chunk前發給這個chunk所在shard以計算分裂點(SplitPoint)時使用的。但是這個命令也可以用於普通的複本集,我們可以把複本集中的集合看作一個唯一的chunk,利用這個命令來為這個chunk計算分裂點,從而達到為某個集合進行分區的目的。
SplitVector命令的使用在官方文檔中沒有介紹,只說明了其實一個內部命令,但是使用命令的Help卻可以看到:
db.runCommand({splitVector:"test.test", help:1}){ "help" : "help for: splitVector Internal command.\nexamples:\n { splitVector : \"blog.post\" , keyPattern:{x:1} , min:{x:10} , max:{x:20}, maxChunkSize:200 }\n maxChunkSize unit in MBs\n May optionally specify 'maxSplitPoints' and 'maxChunkObjects' to avoid traversing the whole chunk\n \n { splitVector : \"blog.post\" , keyPattern:{x:1} , min:{x:10} , max:{x:20}, force: true }\n 'force' will produce one split point even if data is small; defaults to false\nNOTE: This command may take a while to run", "lockType" : 0, "ok" : 1}
從協助文檔中可以大致看到,這個命令大致是這麼使用的:
db.runCommand({splitVector:"blog.post", keyPattern:{x:1}, min{x:10}, max:{x:20}, maxChunkSize:200})
接下來介紹一下各個參數及其含義。 欄位 類型 描述 splitVector string splitVector的操作對象集合名 keyPattern document chunk分裂使用的分區鍵,必須擁有索引,在sharding中就是shard key,在複本集中通常就指定成主鍵_id索引 min document 選擇性參數,分區資料集的最小值,如果沒有指定,那麼使用MinKey max document 選擇性參數,分區資料集的最大值,如果沒有指定,那麼使用MaxKey maxChunkSize integer 選擇性參數,和『force』參數二者必須指定一個。分區後每個chunk的最大大小 maxSplitPoints integer 選擇性參數,分裂點個數上限 maxChunkObjects integer 選擇性參數,分區後每個chunk最大包含的記錄數,預設為250000 force boolean 選擇性參數,和『maxChunkSize』參數二者必須指定一個。預設情況下如果當前chunk的資料大小小於maxChunkSize則不會進行分裂。如果指定了『force』為true,那麼會強制在當前chunk的中位點進行分裂,返回一個分裂點。預設為false。
這麼多參數到底怎麼用呢。我怎麼知道出來的結果是怎樣的。沒有更詳細的文檔,只有啃源碼了。 原理
SplitVector的原理是遍曆指定的『keyPattern』索引,根據指定的『maxChunkSize』找到滿足以下條件的n個分裂點:分裂後的每個新的chunk的大小約為『maxChunkSize』的一半。如果集合當前大小比『maxChunkSize』小或者集合記錄數為空白,那麼返回一個空的分裂點集合。如果指定了『force: true』,那麼會忽略傳入的『maxChunkSize』參數,並強制在集合的中位點進行分區,這時候只會產生一個分裂點。
在尋找分裂點時首先會根據集合的平均文檔大小計算一個分裂後每個chunk所包含的文檔數:
原文連結