PostgreSQL 9.5.4数据库快速INSERT大量数据研究

PostgreSQL 9.5.4数据库快速INSERT大量数据研究

背景

在一些应用场景中,需要向Abase数据库中快速装入大量的数据,比如数据库迁移,SQL日志分析等。在PG上快速插入数据有几种方案,每种方案的效率怎么样?如何调优能加快的数据装载?

场景设定

SQL日志分析是一个采集JDBC日志、分析SQL、发送分析结果工具。在分析阶段,需要解析大量的JDBC日志,并把解析后的结构化结果装入数据库供后续处理。以分析阶段为实验场景,以解析JDBC日志(多个)为开始,以完成结构化数据装入(包过索引建立完成)为结束,来测试不同方案的数据装入效率。

环境准备

  • 数据库环境
名称
操作系统 CENTOS 6.5
CPU Intel(R) Xeon(R) CPU E5-2698 v3 @ 2.30GHz,逻辑64核
内存 316G
磁盘 RAID 10,写入速度1GB/s
数据库版本 PostgreSQL 9.5.4
数据库内存参数 shared_buffers:30G work_mem:4MB maintenance_work_mem:64MB
数据库CPU参数 max_worker_processes:16
  • 建表语句
drop table if exists T_JDBC_SQL_RECORD ;
--无主键,没有用到C_BH 查询,增加insert速度先去掉
create table T_JDBC_SQL_RECORD (
C_BH VARCHAR(32) ,
C_BH_PARSE VARCHAR(32) NULL,
C_BH_GROUP VARCHAR(32) NULL,
C_BH_SQL VARCHAR(32) NULL,
DT_ZXSJ TIMESTAMP NULL,
N_RUNTIME INT NULL,
C_RZLJ VARCHAR(600) NULL,
N_STARTLINE INT NULL,
N_ENDLINE INT NULL,
N_SQLTYPE INT NULL,
N_SQLCOMPLEX INT NULL,
C_IP VARCHAR(100) NULL,
C_PORT VARCHAR(100) NULL,
C_XTBS VARCHAR(100) NULL,
N_CHECKSTATUS INT  default 0,
N_SQL_LENGTH INT NULL,
N_SQL_BYTE INT NULL,
N_5MIN INT NULL,
C_METHOD VARCHAR(600) NULL,
C_PSSQL_HASH VARCHAR(300) NULL,
N_IS_BATCH INT,
N_RESULTSET INT
);

drop table if exists T_JDBC_SQL_CONTENT ;
CREATE TABLE T_JDBC_SQL_CONTENT (
C_BH VARCHAR(32) NOT NULL,
C_PSSQL_HASH VARCHAR(300) NULL,
C_SQL_TEXT varchar NULL,
C_PSSQL_TEXT varchar NULL
);
  • 索引语句
create index i_jdbc_sql_record_zh01 on t_jdbc_sql_record(c_bh_group,dt_zxsj,N_CHECKSTATUS,C_PSSQL_HASH);
create index i_jdbc_sql_record_pshash on t_jdbc_sql_record(c_pssql_hash);
create index i_jdbc_sql_content_pshash on t_jdbc_sql_content(c_pssql_hash);
alter table t_jdbc_sql_content add constraint t_jdbc_sql_content_pkey primary key (C_BH);
  • 异步提交和unlogged table
 -- 异步提交,更改完重启数据库
 alter system set synchronous_commit to off;
 -- unlogged table
 create unlogged table t_jdbc_sql_record
 ...
 create unlogged table t_jdbc_sql_content
 ...
  • JDBC日志量

    19个JDBC日志文件,共2G日志,600万记录

    方案设定

方案名称 方案描述
方案一 建立结构化表及其索引,多线程单个insert装入数据
方案二 建立结构化表及其索引,多线程批量insert装入数据
方案三 建立结构化表及其索引,库设置为异步提交,多线程批量insert装入数据
方案四 建立结构化表,库设置为异步提交,多线程批量insert装入数据,建立索引
方案五 建立结构化表及其索引,表设置为unlogged table,多线程批量insert装入数据
方案六 建立结构化表,表设置为unlogged table,多线程批量insert装入数据,建立索引
方案七 建立结构化表,多线程批量insert装入数据,建立索引

实验结果

每次实验时,解析的JDBC日志量,解析代码和中间件环境保持不变。只调整流程顺序和数据库参数。

实验次数 方案一 方案二 方案三 方案四 方案五 方案六 方案七
第一次 3596s 2043s 1164s 779s 545s 528s 1192s
第二次 4092s 2068s 1283s 843s 528s 528s 1227s
第三次 3891s 2177s 1378s 858s 536s 537s 1248s
平均值 3859s 2096s 1275s 826s 536s 531s 1222s

结果分析

  • 方案一、方案二比较,数据库参数不变,流程顺序不变

    • 方案一:单个insert提交,用时3859秒
    • 方案二:批量insert提交,用时2096秒
  • 方案二、方案三、方案五比较,流程顺序不变,均为建表->建索引->多线程批量插入。
    • 方案二:同步提交(等待WAL日志完成),用时2096秒
    • 方案三:异步提交(不等待WAL日志完成),用时1275秒
    • 方案五:不记录WAL日志,用时536秒
  • 方案二、方案七比较,均为同步提交
    • 方案二:插入数据前建立索引,用时2096秒
    • 方案七:插入数据后建立索引,用时1222秒
  • 方案三、方案四比较,均为异步提交
    • 方案三:插入数据前建立索引,用时1275秒
    • 方案四:插入数据后建立索引,用时826秒
  • 方案五、方案六比较,均为不记录WAL日志
    • 方案五:插入数据前建立索引,用时536秒
    • 方案六:插入数据后建立索引,用时531秒

总结

在该场景下:

  • 批量提交比单个提交快55%
  • 异步提交比同步提交快40%
  • 不记录日志提交比同步提交快75%
  • 记录日志且同步提交时,后建立索引比先建立索引快40%
  • 记录日志且异步提交时,后建立索引比先建立索引快35%
  • 不记录日志时,后建立索引比先建立索引略快,但差别不大

插入数据最快组合为:

unlogged table + 多线程批量insert+后建索引

猜想:

在insert过程中,维护索引的时间占总时间的35%到40%,且主要花费在日志持久化上。

其他:

同时在实验过程中的一些其他指标信息,如不同方案下数据库的写IO从未超过100MB/s,需要继续分析。

时间: 2024-08-01 17:16:25

PostgreSQL 9.5.4数据库快速INSERT大量数据研究的相关文章

怎么从sqlserver 数据库导出 insert 的数据语句

In SSMS in the Object Explorer, right click on the database right-click and pick "Tasks" and then "Generate Scripts". This will allow you to generate scripts for a single or all tables, and one of the options is "Script Data"

数据库快速入门例子代码

数据库快速入门例子代码 下面的内容将简单说明怎样使用数据库.更详细的信息请阅读各个函数的单独介绍页面. 初始化数据库类 下面的代码将依据你的数据库配置载入并初始化数据库类: $this->load->database(); 一旦被载入,你可以在任何地方像这样使用它: 注意: 如果你的所有页面均要求初始化数据库类,你可以让它自动加载.详见 数据库连接. 多结果标准查询(对象形式) $query = $this->db->query('SELECT name, title, email

sql server 数据库机种 insert 语句用法insert into emproyee(e_name,e_sex)values('唐家三少',0); insert into emproyee

刚倒弄sql server 对insert 语句插入多条数据时总结下> 单条数据插入: insert into emproyee(e_name,e_sex)values('唐家三少',0); insert into emproyee(e_name,e_sex)select'骷髅精灵',0 多条数据插入: insert into emproyee(e_name,e_sex)select'天蚕土豆',0 union all select '我吃西红柿',0 union all select '逆苍天

MySql数据库执行insert时候报错:Column count doesn't match value count at row 1

遇到这个问题之后,第一反应就是前后列数不等造成的,但是我检查SQL之后,发现列数是相同得,但是插入还是有问题,然后又写了简单得SQL只插入不为空得字段,执行还是报这个错,最后请教了高人,指点之后,大概是因为当前插入得表被锁住了,然后执行下面得SQL后,之前得SQL就可以正常插入了 LOCK TABLES `system_function_info` WRITE;  UNLOCK TABLES; MySql数据库执行insert时候报错:Column count doesn't match val

Oracle - SQL语句实现数据库快速检索

SQL语句实现数据库快速检索 有时候在数据库Debug过程中,需要快速查找某个关键字. 1:使用PLSQL Dev自带的查找数据库对象,进行对象查找 缺点:查找慢.耗时. 2:使用SQL语句对数据库对象进行查找 查找数据库一般对象 1 SELECT * FROM DBA_SOURCE T WHERE UPPER(T.TEXT) LIKE '%关键字%' 查找数据库脚本 1 SELECT * FROM DBA_JOBS T WHERE UPPER(T.WHAT) LIKE '%关键字%'; 原文地

PHP 数据库驱动、连接数据不同方式学习笔记

相关学习资料 http://www.php.net/manual/zh/refs.database.php http://www.php.net/manual/zh/internals2.pdo.php http://bbs.phpchina.com/thread-184537-1-1.html http://www.metsky.com/archives/660.html http://www.phpbuilder.com/ http://www.w3school.com.cn/php/php

MySQL数据库使用mysqldump导出数据详解

mysqldump是mysql用于转存储数据库的实用程序.它主要产生一个SQL脚本,其中包含从头重新创建数据库所必需的命令CREATE TABLE INSERT等.接下来通过本文给大家介绍MySQL数据库使用mysqldump导出数据详解,需要的朋友一起学习吧 mysqldump是mysql用于转存储数据库的客户端程序.它主要产生一系列的SQL语句,可以封装到文件,该文件包含有所有重建您的数据库所 需要的 SQL命令如CREATE DATABASE,CREATE TABLE,INSERT等等.可

MySQL数据库如何解决大数据量存储问题

利用MySQL数据库如何解决大数据量存储问题? 各位高手您们好,我最近接手公司里一个比较棘手的问题,关于如何利用MySQL存储大数据量的问题,主要是数据库中的两张历史数据表,一张模拟量历史数据和一张开关量历史数据表,这两张表字段设计的很简单(OrderNo,Value,DataTime).基本上每张表每天可以增加几千万条数据,我想问如何存储数据才能不影响检索速度呢?需不需要换oracle数据库呢?因为我是数据库方面的新手,希望可以说的详细一点,万分感谢!!?-0-#暂时可以先考虑用infobri

SQL 快速新增权限数据表(使用cross join)

摘要:SQL 快速新增权限数据表(使用cross join) 1.因为设计系统的时候 将角色 权限 系统都做了分开处理 偏偏交集起来相当多数据 2.决定不自己打 使用cross join 先练习一下一般的语法 --use 数据库 --select a.浏览,a.修改,a.删除,b.系统名称,c.角色名称 --from 角色权限 as a --cross join 系统 as b --cross join 角色 as c --go 像这样 3.开始改写 使用cross join --先清空表单 已