定长记录采用数据库读写并非最佳解决方案

对于有些应用场合如仪器仪表的采样数据,不需要对数据排序、插入和修改,只需要对数据写和读操作,在这种情况下,使用数据库来存取这样的记录数据,未必是最佳的选择,本文根据工作实践,采用文件的分块记录的方法,来处理采样这样的定长记录数据,实践证明,通过文件的分块存储方法,比数据库存储方法读写速度更快,尤其是在处理大批量的记录数据的读写的时候,这种速度上的优势更为显著。下面是分块记录的具体实现方法:

首先,假设我们的记录数据为:记录id号,电流,电压,温度,电阻,用结构体表示为:

[html] view plain copy
 
  1. typedef struct tagRecord {  
  2. quint64 id;  
  3. float cur;  
  4. float vol;  
  5. float tempe;  
  6. float resistor;  
  7. } Trecord;  

那么我们怎么用文件的方式来记录上述数据呢?把文件记录划分为3个部分,文件头,索引块,记录块。

1文件头

[html] view plain copy
 
  1. typedef struct tagFileHead {  
  2. quint8 magic[MAGIC_LEN];  
  3. quint32 version;  
  4. quint32 indexBlkNum;  
  5. } TFileHead;  

(1)magic说明文件是记录文件,这样方便解析,当文件的开头不是magic时,说明这个不是我的文件格式

(2)version方便扩展

(3)indexBlkNum,这个后面会讲,先放一放

2.索引块

[html] view plain copy
 
  1. typedef struct tagBlkHead {  
  2. quint64 nextBlkPos;  
  3. quint32 recordNum;  
  4. }TBlkHead;  
  5.   
  6. typedef struct tagIndexBlk {  
  7. TBlkHead head;  
  8. quint32 blkAddr[INDEX_BLK_RECORD_NUM];  
  9. } TIndexBlk;  

索引块是为了方便记录块的读取而引入的,由两部分组成,块头,nextBlkPos保存当前索引块的下一块位置,recordNum当前索引块的有效记录数,索引块的最大记录数为INDEX_BLK_RECORD_NUM;blkAddr,存放记录块的起始地址。这样的话,在读记录的时候,首先根据索引块建立一个记录块的索引,比如INDEX_BLK_RECORD_NUM = 1000,假如记录块数<1000,那么这样我只需要读1次文件,就可以知道所有记录块的起始地址,有了每个记录块的起始地址,由于记录块记录数也是定值,这样的话,我要访问文件中的任1条记录,只需要读文件1次,从而不管文件的大小,访问文件中的任意1条记录都只需读文件1次。
3.记录块

[html] view plain copy
 
  1. typedef struct tagRecordBlk {  
  2. TBlkHead blkHead;  
  3. TRecord record[RECORD_BLK_RECORD_NUM];  
  4. } TRecordBlk;  

blkHead同上,record这是我们要保存的数据,我们要访问记录号为id的记录,那应怎么访问呢?

[html] view plain copy
 
  1. int blkIndex = id / RECORD_BLK_RECORD_NUM;  
  2. int blkOffset = id % RECORD_BLK_RECORD_NUM;  

只需根据上式先算出该记录在那一块blkIndex,再算出该记录在块中的偏移blkOffset,这样我们就能访问该记录了,根据块索引,我们就能找到块的起始地址,再读出该块,然后根据索引就能访问到该记录了,下图是上图介绍的记录文件的文件组织结构。



 好了今天就写到这里了,明天写实现方式。

http://blog.csdn.net/rabinsong/article/details/8952761

原文地址:https://www.cnblogs.com/findumars/p/5615723.html