manual compaction
手動觸發的compaction。手動觸發的優先級高於自動觸發。
自動觸發的compaction
觸發條件:
imm_ != NULL 表示需要將Memtable dump成SSTable,發起Minor Compaction。
manual_compaction_ != NULL 表示手動發起Compaction。
versions_->NeedsCompaction函數返回True。
注意:在leveldb中,compaction的入口都在 DBImpl::MaybeScheduleCompaction()
Memtable --> Immutable Memtable
Memtable:內存SkipList
簡單理解:從可讀可寫的Memtable變為可讀不可寫的Memtable。
當內存Memtable寫到一定量的時候,會生成新的wal log和新的Memtable。
minor compaction
immutable memtable dump成sstable文件。
Immutable Memtable --> Level0
該過程被成為minor compaction。
Immutable Memtable會在后台線程中導出數據,flush到磁盤上,形成一個新的sstable文件。
注意:這個過程不刪除kv數據。刪除key的信息被記錄進sstable文件。
Level0文件會有多個文件,多個文件的keys range會有重復。
minor compaction主要做兩件事情:
1、構造sstable
2、新的sstable文件寫入哪一層。
代碼流程:
要注意,新成出來的文件不一定處於level0。大都數情況都是level0。
創建出來的新文件處於的層數由PickLevelForMemTableOutput 函數計算。邏輯如下:
在策略上,盡量要將新的compact的文件推到高level。
因為在level 0 需要控制文件過多,compaction IO和查找都比較耗費。
另一方面也不能推至過高level,一定程度上控制查找的次數,而且若某些范圍的key更新比較頻繁,后續往高層compaction IO消耗也很大。
所以PickLevelForMemTableOutput就是個權衡折中。如果新生成的sstable和Level 0的sstable有交疊,新產生的sstable就直接加入level 0,否則根據一定的策略,向上推到Level1 甚至是Level 2,但是最高推到Level2。
這里有一個控制參數:kMaxMemCompactLevel。判斷sstable文件之間key是否有重疊要用到前面介紹的數據結構FileMetaData。
major compaction
當某個Level層級的文件數量超過一定閾值后,會從這個Level的sstable文件將其和高一層級的level+1的sstable文件進行compaction成為新的level+1層的文件。
觸發條件:
bool NeedsCompaction() const {
Version* v = current_;
return (v->compaction_score_ >= 1) || (v->file_to_compact_ != NULL);
}
即
1. 文件數目太多或者某一層級文件總大小過大,會觸發compaction。
某一層及文件個數太多。(指的是level0)
或某一層級文件總大小太大。超過限制值。
2. seek次數太多,觸發compaction
除了level 0以外,任何一個level的文件內部是有序的,文件之間也是有序的。但是level(n)和level(n+1)中的兩個文件的key可能存在交叉。正是因為這種交叉,查找某個key值的時候,level(n) 的查找無功而返,而不得不去level(n+1)查找。如果查找了多次,某個文件不得不查找,卻總也找不到,總是去高一級的level,才能找到。這說明該層級的文件和上一級的文件,key的范圍重疊的很嚴重,這是不合理的,會導致效率的下降。因此,需要對該level 發起一次major compaction,減少 level 和level + 1的重疊情況。
這就是所謂的 Seek Compaction。對於seek觸發的compaction, 哪個文件無效seek的次數到了閾值,那個文件就是level n的參與compaction的文件。而size 觸發的compaction稍微復雜一點,它需要考慮上一次compaction做到了哪個key,什么地方,然后大於該key的第一個文件即為level n的參與compaction的文件。
對於n >0的情況,初選情況下level n的參與compaction文件只會有1個,如果n=0,因為level 0的文件之間,key可能交叉重疊,因此,根據選定的level 0的該文件,得到該文件負責的最小key和最大key,找到所有和這個key 區間有交疊的level 0文件,都加入到參戰文件。
由於level0的特殊性,所以major compaction要分分為兩種:
Level0 --> Level1
選擇一個level0文件。
再找到一個和該level0有重復key的level1文件。
再查找出所有和這個level1文件有重復key的level0文件。
將所有level0文件和level1文件合並成一個新的level1文件。
Level N --> Level N +1
選擇一個 Level N的文件
查找所有和該文件由重復key的Level N +1的文件。
compaction,生成新的Level N + 1的文件。
LevelN
minor compaction主要做兩件事情:1、構造sstable2、新的sstable文件寫入哪一層。