hbase原始碼系列(四)資料模型-表定義和列族定義的具體含義
阿新 • • 發佈:2022-04-29
hbase是一個KeyValue型的資料庫,在《hbase實戰》描述它的邏輯模型【行鍵,列族,列限定符,時間版本】,物理模型是基於列族的。但實際情況是啥?還是上點程式碼吧。
HTableDescriptor tableDesc = new HTableDescriptor("test"); //日誌flush的時候是同步寫,還是非同步寫 tableDesc.setDurability(Durability.SYNC_WAL); //MemStore大小 tableDesc.setMemStoreFlushSize(256*1024*1024); HColumnDescriptor colDesc = new HColumnDescriptor("f"); //塊快取,儲存著每個HFile資料塊的startKey colDesc.setBlockCacheEnabled(true); //塊的大小,預設值是65536 //載入到記憶體當中的資料塊越小,隨機查詢效能更好,越大,連續讀效能更好 colDesc.setBlocksize(64*1024); //bloom過濾器,有ROW和ROWCOL,ROWCOL除了過濾ROW還要過濾列族 colDesc.setBloomFilterType(BloomType.ROW); //寫的時候快取bloom colDesc.setCacheBloomsOnWrite(true); //寫的時候快取索引 colDesc.setCacheIndexesOnWrite(true); //儲存的時候使用壓縮演算法 colDesc.setCompressionType(Algorithm.SNAPPY); //進行compaction的時候使用壓縮演算法 colDesc.setCompactionCompressionType(Algorithm.SNAPPY); //壓縮記憶體和儲存的資料,區別於Snappy colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX); //寫入硬碟的時候是否進行編碼 colDesc.setEncodeOnDisk(true); //關閉的時候,是否剔除快取的塊 colDesc.setEvictBlocksOnClose(true); //是否儲存那些已經刪除掉的kv colDesc.setKeepDeletedCells(false); //讓資料塊快取在LRU快取裡面有更高的優先順序 colDesc.setInMemory(true); //最大最小版本 colDesc.setMaxVersions(3); colDesc.setMinVersions(1); //叢集間複製的時候,如果被設定成REPLICATION_SCOPE_LOCAL就不能被複制了 colDesc.setScope(HConstants.REPLICATION_SCOPE_GLOBAL); //生存時間 colDesc.setTimeToLive(18000); tableDesc.addFamily(colDesc);
在上面列出來表定義和列族定義的所有引數,含義也標上去了,我們經常需要設定的可能就是下面的這些。
//bloom過濾器,過濾加速 colDesc.setBloomFilterType(BloomType.ROW); //壓縮記憶體和儲存中的資料,記憶體緊張的時候設定 colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX); //讓資料塊快取在LRU快取裡面有更高的優先順序 colDesc.setInMemory(true); //最大版本,沒必要的話,就設定成1個 colDesc.setMaxVersions(1); //叢集間複製的時候,如果被設定成REPLICATION_SCOPE_LOCAL就不能被複制了 colDesc.setScope(HConstants.REPLICATION_SCOPE_GLOBAL); //儲存的時候使用壓縮演算法,這個基本是必備的,hbase的儲存大得驚人 colDesc.setCompressionType(Algorithm.SNAPPY); //進行compaction的時候使用壓縮演算法 colDesc.setCompactionCompressionType(Algorithm.SNAPPY);
hbase的表在hdfs上面的是這麼儲存的,/hbase-root/tableName/regionName/familyName/HFile, 在tableName這一級目錄會有一個名.tabledesc的檔案,在region這一級目錄有一個名為.regioninfo的檔案,都是明文的。
瞭解完表和列族的定義之後,我們看看KeyValue是怎麼儲存的吧,引用一下程式碼,可能大家一看就都懂了。
@Override public void write(Cell cell) throws IOException { checkFlushed(); // Row rowkey,起始位置,長度 write(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()); // Column family 列族,起始位置,長度 write(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()); // Qualifier 列名,起始位置,長度 write(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()); // Version 時間戳 this.out.write(Bytes.toBytes(cell.getTimestamp())); // Type Put或者Delete this.out.write(cell.getTypeByte()); // Value 值,起始位置,長度 write(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()); }
好吧,列儲存的話儲存的時候每個列都會重複前面的rowkey、列族這些資訊,在列很多的情況下,rowkey和列族越長,消耗的記憶體和列族都會很大,所以它們都要儘量的短。
可以考慮用colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX_TREE)來壓縮一下記憶體中的大小,這個後面後面會講到。