1. 程式人生 > 其它 >hbase原始碼系列(四)資料模型-表定義和列族定義的具體含義

hbase原始碼系列(四)資料模型-表定義和列族定義的具體含義

  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)來壓縮一下記憶體中的大小,這個後面後面會講到。