查看: 3902|回复: 1

通过解析Hfile的index结构获取数据分布情况

[复制链接]
论坛徽章:
36
ITPUB元老
日期:2007-08-14 09:10:50美羊羊
日期:2015-06-08 11:13:51懒羊羊
日期:2015-05-27 14:41:362015年新春福章
日期:2015-03-06 11:57:31美羊羊
日期:2015-03-04 14:48:58马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14
发表于 2012-6-15 15:03 | 显示全部楼层 |阅读模式
有时候开发应用人员并不一定了解hbase中表的数据分布,也很难提供表的split规则,此时需要一种方法来获得hfile本身的数据分布信息。
对于hfile来说,会有一个index结构,这个结构类似于oracle的b-tree索引。与读取全部的hfile中的记录来比,直接分析索引的结构更加高效。

详细的代码如下:
  1. import java.io.IOException;
  2. import java.nio.ByteBuffer;
  3. import java.util.HashMap;
  4. import java.util.Iterator;
  5. import java.util.LinkedHashMap;
  6. import java.util.Map;

  7. import org.apache.hadoop.conf.Configuration;
  8. import org.apache.hadoop.fs.FSDataInputStream;
  9. import org.apache.hadoop.fs.FileSystem;
  10. import org.apache.hadoop.fs.Path;
  11. import org.apache.hadoop.hbase.KeyValue;
  12. import org.apache.hadoop.hbase.KeyValue.KeyComparator;
  13. import org.apache.hadoop.hbase.io.hfile.BlockType;
  14. import org.apache.hadoop.hbase.io.hfile.Compression;
  15. import org.apache.hadoop.hbase.io.hfile.FixedFileTrailer;
  16. import org.apache.hadoop.hbase.io.hfile.HFileBlock;
  17. import org.apache.hadoop.hbase.io.hfile.HFileBlock.FSReader;
  18. import org.apache.hadoop.hbase.io.hfile.HFileBlockIndex;
  19. import org.apache.hadoop.hbase.util.Bytes;
  20. import org.apache.hadoop.io.RawComparator;

  21. public class Analyze_Hfile_Index {
  22.        
  23.         private String hdfs;
  24.         private String hfile;
  25.        
  26.         HashMap<Long, Integer> block_p = new LinkedHashMap<Long, Integer>();
  27.         HashMap<Long, Integer> block_c = new LinkedHashMap<Long, Integer>();
  28.        
  29.         private Configuration conf;
  30.         private FileSystem fs;
  31.         private FSDataInputStream fdis;
  32.         private long hfilesize;
  33.         private Compression.Algorithm compressAlgo;
  34.         private FixedFileTrailer trailer;
  35.         private FSReader fsBlockReader;
  36.         private int DataIndexLevel;
  37.         private String comparatorClassName;
  38.         private RawComparator<byte []> comparator;
  39.         private HFileBlockIndex.BlockIndexReader dataBlockIndexReader;
  40.         private HFileBlock.BlockIterator blockIter;
  41.        
  42.         final int SECONDARY_INDEX_ENTRY_OVERHEAD = Bytes.SIZEOF_INT + Bytes.SIZEOF_LONG;
  43.        
  44.         public Analyze_Hfile_Index(String hdfs, String hfile) throws IOException {
  45.                 this.hdfs = hdfs;
  46.                 this.hfile = hfile;
  47.                
  48.                 Path phfile = new Path(hfile);
  49.                
  50.                 conf = new Configuration();
  51.                 conf.set("fs.default.name", hdfs);
  52.                 fs = FileSystem.get(conf);       
  53.                 fdis = fs.open(phfile);
  54.                 hfilesize = fs.getFileStatus(phfile).getLen();
  55.                 trailer = FixedFileTrailer.readFromStream(fdis, hfilesize);
  56.                 trailer.expectVersion(2);
  57.                 compressAlgo = trailer.getCompressionCodec();
  58.                 fsBlockReader = new HFileBlock.FSReaderV2(fdis,compressAlgo,hfilesize);
  59.                 DataIndexLevel = trailer.getNumDataIndexLevels();
  60.                 comparatorClassName = KeyComparator.class.getName();
  61.                 comparator = FixedFileTrailer.createComparator(comparatorClassName);
  62.                 blockIter = fsBlockReader.blockRange(
  63.             trailer.getLoadOnOpenDataOffset(),hfilesize - trailer.getTrailerSize());       
  64.         }
  65.        
  66.         public int get_DataIndexLevel() {
  67.                 return DataIndexLevel;
  68.         }
  69.        
  70.         public void get_RootIndex(boolean stop) throws IOException {
  71.             dataBlockIndexReader = new HFileBlockIndex.BlockIndexReader(comparator,
  72.                             trailer.getNumDataIndexLevels());
  73.             
  74.             dataBlockIndexReader.readMultiLevelIndexRoot(
  75.                     blockIter.nextBlockAsStream(BlockType.ROOT_INDEX),
  76.                     trailer.getDataIndexCount());         
  77.             
  78.             System.out.println("Root Index:");
  79.             
  80.             for(int i=0; i<trailer.getDataIndexCount(); i++) {
  81.                     byte[] RootBlockKey = dataBlockIndexReader.getRootBlockKey(i);
  82.                     long RootBlockOffset = dataBlockIndexReader.getRootBlockOffset(i);
  83.                     int RootBlockDataSize = dataBlockIndexReader.getRootBlockDataSize(i);
  84.                    
  85.                     if(!stop) {
  86.                             block_p.put(RootBlockOffset, RootBlockDataSize);
  87.                     }
  88.                    
  89.                     System.out.println(KeyValue.keyToString(RootBlockKey));
  90.             }
  91.             System.out.println("=================================================================");            
  92.         }
  93.        
  94.         public void get_NoRootIndex(int level,boolean stop) throws IOException {
  95.                
  96.                 System.out.println("NoRoot Index:"+level);
  97.                
  98.                 int i=0;
  99.                
  100.                 Iterator iter = block_p.entrySet().iterator();
  101.                
  102.                 while (iter.hasNext()) {
  103.                         Map.Entry entry = (Map.Entry) iter.next();
  104.                     long blockOffsets = (Long) entry.getKey();
  105.                     int blockDataSizes = (Integer) entry.getValue();

  106.                         System.out.println("Index:"+i++);
  107.                        
  108.                         HFileBlock hfb = fsBlockReader.readBlockData(blockOffsets, blockDataSizes, -1, false);
  109.                         ByteBuffer buffer = hfb.getBufferWithoutHeader();
  110.                        
  111.                         int numEntries = buffer.getInt(0);
  112.                     
  113.                     int entriesOffset = Bytes.SIZEOF_INT * (numEntries + 2);
  114.                     
  115.                     for(int j=0; j<numEntries; j++) {
  116.                             int KeyRelOffset = buffer.getInt(Bytes.SIZEOF_INT * (j + 1));
  117.                             int KeyOffset = entriesOffset + KeyRelOffset + SECONDARY_INDEX_ENTRY_OVERHEAD;  
  118.                            
  119.                             long NoRootBlockOffset = buffer.getLong(entriesOffset + KeyRelOffset);
  120.                             int NoRootBlockDataSize = buffer.getInt(entriesOffset + KeyRelOffset+Bytes.SIZEOF_LONG);                   
  121.            
  122.                             int Length = buffer.getInt(Bytes.SIZEOF_INT * (j + 2)) - KeyRelOffset - SECONDARY_INDEX_ENTRY_OVERHEAD;

  123.                             byte[] tt = new byte[Length];

  124.                             System.arraycopy(buffer.array(), buffer.arrayOffset() + KeyOffset, tt, 0, Length);
  125.                             System.out.println(KeyValue.keyToString(tt));
  126.                            
  127.                             if(!stop) {
  128.                                     block_c.put(NoRootBlockOffset, NoRootBlockDataSize);
  129.                             }
  130.                 
  131.                     }
  132.                     System.out.println("---------------------------------------------------");
  133.                 }

  134.                 System.out.println("=================================================================");
  135.                
  136.             if(!stop) {
  137.                     block_p.clear();
  138.                     block_p = (HashMap<Long, Integer>) block_c.clone();
  139.                     block_c.clear();
  140.             }               
  141.         }
  142.        
  143.         public static void main(String[] args) throws IOException {
  144.                
  145.                 String hdfs = args[0];
  146.                 String hfile = args[1];
  147.                 int level = Integer.parseInt(args[2]);
  148.                
  149.                 Analyze_Hfile_Index ri = new Analyze_Hfile_Index(hdfs,hfile);
  150.                
  151.                 if(ri.get_DataIndexLevel() == 0) {
  152.                         System.out.println("ERROR:Hfile has no indexes,please check it!");
  153.                         return;                       
  154.                 }
  155.                
  156.                 if(level > ri.get_DataIndexLevel()) {
  157.                         System.out.println("ERROR:DataIndexLevel="+ri.get_DataIndexLevel()+",please check it!");
  158.                         return;
  159.                 }
  160.                
  161.                 if(level<=1) {
  162.                         ri.get_RootIndex(true);
  163.                         return;
  164.                 } else {
  165.                         ri.get_RootIndex(false);
  166.                         for(int i=1; i<level - 1; i++) {
  167.                                 ri.get_NoRootIndex(i,false);
  168.                         }
  169.                 }
  170.                
  171.                 ri.get_NoRootIndex(1,true);
  172.         }

  173. }
复制代码

编译方式:
  1. javac Analyze_Hfile_Index.java -classpath $HBASE_HOME/lib/guava-r09.jar:$HBASE_HOME/lib/guava-r09-jarjar.jar:$HBASE_HOME/lib/commons-logging-1.1.1.jar:$HBASE_HOME/lib/hadoop-core-0.20.2-cdh3u3.jar:./:$HBASE_HOME/hbase-0.92.0.jar
复制代码

参数说明:
参数1:hdfs的ip加端口
参数2:hfile在hdfs上的地址
参数3:index分析的层数

使用举例:
  1. [hadoop@hadoop01 test01]$ java Analyze_Hfile_Index hdfs://hadoop01:9000 /hbase/sunwg03/f66349e1c8f59c2e3db427dd5c4709a3/f1/d657d57d512a452db1313b2423d123fe 1
  2. Root Index:
  3. 0/f1:k1/1338283872872/Put
  4. 199871/f1:k1/1338283994959/Put
  5. 299744/f1:k1/1338284043637/Put
  6. 399617/f1:k1/1338284089844/Put
  7. 499490/f1:k1/1338284138968/Put
  8. 599363/f1:k1/1338284190201/Put
  9. 699236/f1:k1/1338284240781/Put
  10. 799109/f1:k1/1338284289698/Put
复制代码
结果说明:根结点有8条记录,每条记录表示一个二级索引块的位置。如果此时想对该hfile进行split,split分成4个region,那么就可以对上面8条记录进行分析得到相对比较平均的分布


论坛徽章:
0
发表于 2012-6-18 12:38 | 显示全部楼层
来给你顶顶

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 
京ICP备09055130号-4  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表