1.record概念

Record是从使用者角度来说的,如使用PhysicalRowIdManager插入一个10000byte的Record
 
    byte[] data = TestUtil.makeRecord(10000, (byte) 1);

    Location loc = physMgr.insert( data, 0, data.length );

每一个记录都会被DataPage和RecordHeader进行封装:

    curBlock = file.get( start );
    curPage = DataPage.getDataPageView( curBlock );
    curPage.setFirst( DataPage.O_DATA );
    RecordHeader hdr = new RecordHeader( curBlock, DataPage.O_DATA );
    hdr.setAvailableSize( 0 );
    hdr.setCurrentSize( 0 );
   
一个BlockIo最多只能存储8164(RecordFile.BLOCK_SIZE - DataPage.O_DATA - RecordHeader.SIZE)个bytes
如果不需要RecordHeader(这个BlockIo全都是data,不需要RecordHeader),那么可以存储8172(RecordFile.BLOCK_SIZE - DataPage.O_DATA)个bytes。两者相差RecordHeader.SIZE(8)个bytes。

    curBlock = file.get( start );
    curPage = DataPage.getDataPageView( curBlock );
    curPage.setFirst( (short) 0 ); // no rowids, just data

上面最后一行代码curPage.setFirst( (short) 0 )并不是说从0的位置开始可以存储数据,而是从DataPage.O_DATA(20)开始存储数据:
 
       if ( leftToWrite > 0 ) {
                block = file.get( curs.next() );
                dataOffset = DataPage.O_DATA;
        }

2.JDBM效率

顺序插入记录的时候,BlockIo能够非常紧凑的使用,不会出现多余的空间遗漏,比如上面插入10000个bytes,那么第二次插入10000时,那么从第一次结束的地方开始(第二个BlockIo的offset为10000-8164+20=1856)安排第一个记录。但是如果一旦出现update的情况则不一样了,比如10000个bytes的记录被update成20000个bytes,JDBM会释放这个10000bytes的空间,在FREEPHYSIDS_PAGE中就多一个10000bytes的slot待使用。这个时候如果插入一个20bytes的记录,那么就独占这个10000bytes的空间,这就造成空间浪费。这种策略只适合查询较多的情况,不适合频繁的更新,当然可以优化,只从这个slot中取20+28个bytes空间,其他的依然放在这个slot中待使用。如果有时间,我想试试。