PgSQL批量插入測試數據


PgSQL批量插入測試數據

1 pgsql批量插入測試數據測試

1.1 測試准備

-- 1.創建測試表t_user
create table if not exists t_user(
	id serial primary key,
	user_name varchar(255),
	pass_word varchar(255),
	create_time date,
	dr char(1)
)
 
-- 2.注釋
comment on column t_user.id is '測試表';
comment on column t_user.user_name is '賬號';
comment on column t_user.pass_word is '密碼';
comment on column t_user.create_time is '創建日期';
comment on column t_user.dr is 'delete remark';

1.2 測試4種不同的批量插入測試數據效率

1.2.1 創建存儲過程

-- 創建存儲過程插入數據
create or replace function batch_insert_proc(num int) returns void as 
$$
begin
	while num > 0 loop
		insert into t_user(user_name,pass_word,create_time,dr) values('username'||round(random()*num),'password'||round(random()*num),now(),0);
		num = num -1;
	end loop;
exception
	when others then
	raise exception'(%)',SQLERRM;
end;
$$ language plpgsql;

1.2.2 直接調用存儲過程

-- 插入100*10000條數據
select batch_insert_proc(100*10000); 

1.2.3 嘗試關閉自動提交調用存儲過程

-- 也可以使用set autocommit off關閉自動提交
START TRANSACTION;
    select batch_insert_proc(100*10000);
commit;

1.2.4 直接使用插入語句

insert into t_user select generate_series(1,100*10000),'username'||round(random()*1000000),'password'||round(random()*1000000),now(),0;

1.2.5 直接使用插入語句並關閉自動提交

start transaction;
	insert into t_user select         generate_series(1,100*10000),'username'||round(random()*1000000),'password'||round(random()*1000000),now(),0;
commit;

1.3 測試復制表效率

1.3.1 導出導入數據文件並使用copy復制

-- 導出數據到文件(100*10000條記錄)
copy t_user to 'E:\\sql\\user.sql';
-- 復制表結構
create table t_user_copy as (select * from t_user limit 0);
-- 從數據文件copy數據到新表
copy t_user_copy from 'E:\\sql\\user.sql';

1.3.2 直接使用sql語句復制

-- 測試2:直接復制表結構及數據(100W耗時3.445秒)
create table t_user_copy as (select * from t_user);

1.4 總結

1、插入測試數據直接使用2.4,復制表數據使用copy即可。

2、postgresql在function不能用start transaction, commit 或rollback,因為函數中的事務其實就是begin...exception.end塊。所有你如果要寫事務,請直接用begin...exception...end就夠了,這也說明了為什么上面開啟事務,或者換種說法關閉自動提交根本就沒有提升批量插入數據的性能,但是copy確實對性能提升有一定幫助。

3、postgresql在函數(存儲過程)中引入了異常的概念,即begin...exception...end塊,這里有三種情況,第一種:這個函數體的結構就是一個全局的begin...exception...end塊(后文簡稱bee塊),可以把bee塊理解為一個事務,當這個函數體,即全局事務出現異常,則全部rollback。第二種情況:如果在某個子bee塊中出現異常,則該bee塊會回滾,但是不會影響其它bee塊。感覺pgsql在函數這塊得些細節整得有點晦澀難懂。

2 postgres 使用存儲過程批量插入數據

create or replace function creatData2() returns 
boolean AS
$BODY$
declare ii integer;
  begin
  II:=1;
  FOR ii IN 1..10000000 LOOP
  INSERT INTO ipm_model_history_data (res_model, res_id) VALUES (116, ii);
  end loop;
  return true;
  end;
$BODY$
LANGUAGE plpgsql;
select * from creatData2() as tab;
create or replace function creatData2() returns 
boolean AS
$BODY$
declare ii integer;
begin
II:=1;
FOR ii IN 1000..2000 LOOP
INSERT INTO "t_member_score_item2"("member_score_item_id", "member_code", "score_type", "score", "sys_no", "remark", "insert_time", "insert_oper", "update_time", "update_oper") VALUES
(ii, '01862204522573', '06', '100.000000', '04', NULL, now(), 'mv', now(), 'mv');
end loop;
return true;
end;
$BODY$
LANGUAGE plpgsql;


select * from creatData2() as tab;
select * from t_member_score_item2

3 pgsql 批量插入數據(含數組使用)

do $$
declare 
i integer; -- 定義使用變量
 testArr varchar array; -- 數組定義
begin -- 開始
i :=2200;
testArr := array['張三','李四','王五','六七'];
for index in 1..array_length(testArr, 1) loop -- 循環開始
INSERT INTO public.wares (id,w_name,w_alias,w_unit,w_cost,w_sellprice,w_minnum,w_maxnum,w_description,w_purchase_date,s_id,w_vaild_date,remark,valid_flag,create_date,creator,update_date,updater) VALUES 
(i,testArr[index],testArr[index],'斤',4.000,3.400,20.000,20.000,NULL, now(),NULL,now(),NULL,'1',now(),'管理員',NULL,NULL);
i = i+1;
end loop; -- 循環結束
end $$;

4 postgreSQL數據庫 實現向表中快速插入1000000條數據

create table tbl_test (id int, info text, c_time timestamp);

--隨機字母 
select chr(int4(random()*26)+65);

--隨機4位字母
select repeat( chr(int4(random()*26)+65),4);

--隨機數字 十位不超過6的兩位數
select (random()*(6^2))::integer;

--三位數
select (random()*(10^3))::integer;

insert into t_test SELECT generate_series(1,10000) as key,repeat( chr(int4(random()*26)+65),4), (random()*(6^2))::integer,null,(random()*(10^4))::integer;

5 批量插入

批量插入是指一次性插入多條數據,主要用於提升數據插入效率,PostgreSQL有多種方法實現批量插入。

5.1 方式一:INSERT INTO…SELECT…

通過表數據或函數批量插入,語法如下:

INSERT INTO table_name SELECT...FROM source_table 

比如創建一張表結構和user_ini相同的表並插入user_ini表的全量數據,代碼如下所示:

mydb=> CREATE TABLE tbl_batch1(user_id int8,user_name text);
CREATE TABLE 
mydb=> INSERT INTO tbl_batch1(user_id,user_name) SELECT user_id,user_name FROM user_ini; 
INSERT 0 1000000 

以上示例將表user_ini的user_id、user_name字段所有數據插入表tbl_batch1,也可以插入一部分數據,插入時指定where 條件即可。 通過函數進行批量插入,如下所示:

mydb=> CREATE TABLE tbl_batch2 (id int4,info text); 
CREATE TABLE
mydb=> INSERT INTO tbl_batch2(id,info) 
	   SELECT generate_series(1,5),'batch2'; 
INSERT 0 5 

通過SELECT表數據批量插入的方式大多關系型數據庫都支持,接下來看看PostgreSQL支持的其他批量插入方式。

5.2 方式二:INSERT INTO VALUES(), (),…()

PostgreSQL的另一種支持批量插入的方法為在一條 INSERT語句中通過VALUES關鍵字插入多條記錄,通過一個 例子就很容易理解,如下所示:

mydb=> CREATE TABLE tbl_batch3(id int4,info text); 
CREATE TABLE 
mydb=> INSERT INTO tbl_batch3(id,info) VALUES (1,'a'),(2,'b'),(3,'c'); 
INSERT 0 3 

數據如下所示:

mydb=> SELECT * FROM tbl_batch3; 
id | info 
-------+------ 
	 1 | a 
	 2 | b 
	 3 | c 
(3 rows) 

這種批量插入方式非常獨特,一條SQL插入多行數據,相 比一條SQL插入一條數據的方式能減少和數據庫的交互,減少數據庫WAL(Write-Ahead Logging)日志的生成,提升插入效率,通常很少有開發人員了解PostgreSQL的這種批量插入方 式。

5.3 方式三:COPY或\COPY元命令

前面介紹了psql導入、導出表數據,使用的是COPY命令或\copy元命令,copy或\copy元命令能夠將一定格式的文件數據導入到數據庫中,相比INSERT命令插入效率更高,通常大數據量的文件導入一般在數據庫服務端主機通過PostgreSQL 超級用戶使用COPY命令導入,下面通過一個例子簡單看看 COPY命令的效率,測試機為一台物理機上的虛機,配置為4核CPU,8GB內存。 首先創建一張測試表並插入一千萬數據,如下所示:

mydb=> CREATE TABLE tbl_batch4( id int4, info text, create_time timestamp(6) with time zone default clock_timestamp()); 
CREATE TABLE 
mydb=> INSERT INTO tbl_batch4(id,info) SELECT n,n||'_batch4' FROM generate_series(1,10000000) n; 
INSERT 0 10000000 

以上示例通過INSERT插入一千萬數據,將一千萬數據導出到文件,如下所示:

[postgres@pghost1 ~]$ psql mydb postgres 
psql (10.0) 
Type "help" for help.
mydb=# \timing 
Timing is on. 
mydb=# COPY pguser.tbl_batch4 TO '/home/pg10/tbl_batch4.txt'; 
COPY 10000000 
Time: 6575.787 ms (00:06.576) 

一千萬數據導出花了6575毫秒,之后清空表tbl_batch4並將文件tbl_batch4.txt的一千萬數據導入到表中,如下所示:

mydb=# TRUNCATE TABLE pguser.tbl_batch4; 
TRUNCATE TABLE 
mydb=# COPY pguser.tbl_batch4 FROM '/home/pg10/tbl_batch4.txt'; 
COPY 10000000 
Time: 15663.834 ms (00:15.664) 

一千萬數據通過COPY命令導入執行時間為15663毫秒。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM