大文本数据的数据库存储

作者: AndyCLanguage | 来源:发表于2017-02-20 11:50 被阅读0次

要点####

  • 文件数据的读取相较数据库的存储较快
  • Android系统对单个应用的内存有限制
  • 数据库操作中对数据的批插入比单个插入效率更高
  • 合理利用多线程能够大大提高工作效率

背景####

项目有一个需求就是将文本文件解析,然后保存到数据库中。最初的思考方式是采用读取文件一行数据(按行存储一个实体变量数据),解析数据为实体类,然后将该实体类存储至数据库中;该方法在测试过程中有一个致命缺点:处理时间长

分析####

将上述流程转化为比较容易理解的抽象图,如下:

文件数据保存至数据库(未优化).png

将子公司货物(单行数据)快速打包成货物(解析)并运送至交接位置处(内存),然后交由速度较慢的运送方式将货物运送至总部(数据库)。该方式为顺序流程,当货物运送至总部后才会再次从子公司重新开始运送货物。该方式有几个缺点:

  • 顺序流程增加了总时间:数据插入时间+数据的处理时间,如果采用多线程将会大幅度减少总时间
  • 数据的单个插入增加了数据插入时间

优化####

通过分析将流程优化,优化后的抽象图如下:


文件数据保存至数据库(已优化).png

该流程分为两部分:

  • 将子公司货物(单行数据)快速打包成货物(解析)并运送至仓库(内存队列);
  • 从仓库中取出合适数量的货物(批量数据)运送至总部(数据库)

  该流程利用了多线程将流程分为两部分——数据存储数据解析,数据存储的速度较慢,因此最后总时间的计算是以数据存储为依据,也就是数据插入时间
  另一方面,程序使用了仓库,也就是队列的方式优化了数据的交接方式,将数据存储与数据解析分离,他们只通过队列才产生耦合。但是因为Android对内存的限制,所以需要合理设计仓库的大小,以防出现内存溢出。

注意:合理的设计数据解析与数据存储流程对队列的数据读写速度。

Code####

  通过上述的代码分析,应该对整体的流程有一个大概的思路,现在我们来看一下代码:

  • 队列的定义与初始化:
LinkedBlockingQueue queue = new LinkedBlockingQueue();
  • 主要流程代码:
try {
    BufferedReader reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(new FileInputStream(path))));
    String line = null;
    //初始化数据存储线程
    WriteDB writeDB = new WriteDB();
    new Thread(writeDB).start();
    //读取文本文件,并解析
    while ((line = reader.readLine())!=null){
        //通过该函数解析数据
        parase(line);
        //查询队列中的数据量,当数据为8000条时暂停数据解析线程
        if(queue.size() == 8000){
            Thread.currentThread().sleep(2*1000);
        }
    }
    reader.close();
    //告知数据存储线程读取线程结束
    writeDB.stop();

} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}
  • 数据解析流程:
private void parase(String s) throws Exception{
     //根据规则解析单行数据,并转化为实体
     String[] list = s.split("\\|");
     BagInfo bag = new BagInfo();
     bag.setBagID(list[0]);
     bag.setPileID(list[1]);
     bag.setTrayID(list[2]);
     //存入队列中
     queue.put(bag);
}
  • 数据存储流程:
class WriteDB implements Runnable {
    private boolean isRun = true;
    @Override
    public void run() {
        //为了批量存储设置的列表,保存从队列中读取的数据
        List<BagInfo> bagInfos = new ArrayList<>();
        while (isRun || !queue.isEmpty()){
            Object obj = null;
            try {
                obj = queue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            bagInfos.add((BagInfo) obj);
            //当列表中的数据量达到2000时将数据批量存储至数据库中
            if(bagInfos.size() == 2000){
                DBService.getService().getBagInfoDao().insertInTx(bagInfos);
                bagInfos.clear();
            }
        }
        //处理当总数据量不是2000的整数倍时所剩余的数据
        if(!bagInfos.isEmpty()){
            DBService.getService().getBagInfoDao().insertInTx(bagInfos);
            bagInfos.clear();
        }
        queue = null;
    }

    public void stop(){
        isRun =false;
    }
}

后台监测####

  运行程序并监测后台,发现内存基本稳定在6M左右;测试5W多条的数据量总花费的时间为68s左右。监测图如下:

后台监测图.png

相关文章

  • 大文本数据的数据库存储

    要点#### 文件数据的读取相较数据库的存储较快 Android系统对单个应用的内存有限制 数据库操作中对数据的批...

  • 数据库系统概述(数据库基本概念)

    数据(Data) 数据是数据库中存储的基本对象。 数据的种类很多,如文本(Text)、图形(Graph)、图像(I...

  • 爬虫 之 数据存储

    爬虫采集下来的数据我们需要将其存储起来,可以存储为文本,也可以将其存到数据库中,下面简单介绍一下存入数据库中 首先...

  • 5数据库技术基础

    数库基础概念 数据库系统 数据是数据库中存储的基本对象,是描述事物的符号记录。数据的种类:文本、图形、图像、音频、...

  • DDIA(三)

    存储与检索 数据库核心:数据结构 世界上最简单的数据库可以用两个Bash函数实现: 底层的存储格式: 一个文本文件...

  • oracle

    oracle 数据库 java编写一个程序 数据存在哪里呢?目前: 数组 集合文本文件一、数据的存储文本文件存...

  • 51cto赵强HADOOP学习(十三)hive的数据存储

    基于HDFS 没有专门的数据存储格式 存储结构主要包括:数据库、文件、表、视图 可以直接加载文本文件(.txt文件...

  • NoSQL数据库的四大类型

    一般将NoSQL数据库分为四大类:键值(Key-Value)存储数据库、列存储数据库、文档型数据库和图形(Grap...

  • iOS sqlite3数据库使用复习

    iOS APP的数据存储方式有很多,NSUserDefault、plist、归档存到文本文件、sqlite3数据库...

  • 监控系列讲座(二)常用的监控数据库

    2. 常用的监控数据库 2.1. 监控数据的存储软件 说到监控数据的存储软禁,无非就是在说数据库。咱们现在常见的大...

网友评论

    本文标题:大文本数据的数据库存储

    本文链接:https://www.haomeiwen.com/subject/vioqwttx.html