定长记录采用数据库读写并非最佳解决方案
对于有些应用场合如仪器仪表的采样数据,不需要对数据排序、插入和修改,只需要对数据写和读操作,在这种情况下,使用数据库来存取这样的记录数据,未必是最佳的选择,本文根据工作实践,采用文件的分块记录的方法,来处理采样这样的定长记录数据,实践证明,通过文件的分块存储方法,比数据库存储方法读写速度更快,尤其是在处理大批量的记录数据的读写的时候,这种速度上的优势更为显著。下面是分块记录的具体实现方法:
首先,假设我们的记录数据为:记录id号,电流,电压,温度,电阻,用结构体表示为:
- typedef struct tagRecord {
- quint64 id;
- float cur;
- float vol;
- float tempe;
- float resistor;
- } Trecord;
那么我们怎么用文件的方式来记录上述数据呢?把文件记录划分为3个部分,文件头,索引块,记录块。
1文件头
- typedef struct tagFileHead {
- quint8 magic[MAGIC_LEN];
- quint32 version;
- quint32 indexBlkNum;
- } TFileHead;
(1)magic说明文件是记录文件,这样方便解析,当文件的开头不是magic时,说明这个不是我的文件格式
(2)version方便扩展
(3)indexBlkNum,这个后面会讲,先放一放
2.索引块
- typedef struct tagBlkHead {
- quint64 nextBlkPos;
- quint32 recordNum;
- }TBlkHead;
- typedef struct tagIndexBlk {
- TBlkHead head;
- quint32 blkAddr[INDEX_BLK_RECORD_NUM];
- } TIndexBlk;
索引块是为了方便记录块的读取而引入的,由两部分组成,块头,nextBlkPos保存当前索引块的下一块位置,recordNum当前索引块的有效记录数,索引块的最大记录数为INDEX_BLK_RECORD_NUM;blkAddr,存放记录块的起始地址。这样的话,在读记录的时候,首先根据索引块建立一个记录块的索引,比如INDEX_BLK_RECORD_NUM = 1000,假如记录块数<1000,那么这样我只需要读1次文件,就可以知道所有记录块的起始地址,有了每个记录块的起始地址,由于记录块记录数也是定值,这样的话,我要访问文件中的任1条记录,只需要读文件1次,从而不管文件的大小,访问文件中的任意1条记录都只需读文件1次。
3.记录块
- typedef struct tagRecordBlk {
- TBlkHead blkHead;
- TRecord record[RECORD_BLK_RECORD_NUM];
- } TRecordBlk;
blkHead同上,record这是我们要保存的数据,我们要访问记录号为id的记录,那应怎么访问呢?
- int blkIndex = id / RECORD_BLK_RECORD_NUM;
- int blkOffset = id % RECORD_BLK_RECORD_NUM;
只需根据上式先算出该记录在那一块blkIndex,再算出该记录在块中的偏移blkOffset,这样我们就能访问该记录了,根据块索引,我们就能找到块的起始地址,再读出该块,然后根据索引就能访问到该记录了,下图是上图介绍的记录文件的文件组织结构。
好了今天就写到这里了,明天写实现方式。
http://blog.csdn.net/rabinsong/article/details/8952761