DB插入性能大乱斗 - postgresql vs mysql vs mongodb vs oracle
因为看到德哥的postgresql与
mongodb插入100万条记录的比较文章,想动手验证一下,但结论反正让我看不懂了!
首先我是在虚拟机上测试,4核8G+存储,centos7.2,mongo3.2.9,postgresql9.6开发版,都是最新版,新安装不作任何处理;
都通过python来测试,但mongodb的测试结果是371秒,跟德哥的测试接近;
可pg就奇怪了,跑了十几分钟,还只看记录达到56万,实在是慢得出奇;
我估计存储方面有限制或者开发版有BUG吧,换物理机来测;
硬件,普通PC机,win10系统:
PG,之前官网下载的9.5.2windows版,全新安装不作任何设置:
这下能跑完了,但239秒跟德哥的测试有些差距,脚本中有一个区别,就是不是unix_socket连接(搞不清unix_socket连接名称在哪找);
由于mongodb还没装,但有一个很早之前下载的
mysql绿色版,版本号都6.0.5了,非官方,但能用:
小测一把,竟然102秒就跑完了!(后来我又在虚拟机上安装了mariadb5.5.50,测试结果也是102秒!)
这是PG的测试脚本:
import psycopg2
import time
conn=psycopg2.connect(database="test1",user="postgres",password="",host="127.0.0.1",port="5432")
cur=conn.cursor()
conn.autocommit=True
start_t=time.time()
print("START:"+str(start_t))
for i in range(0,1000000):
cur.execute("insert into tt values(%(id)s,'digoal.zhou',32,'digoal@126.com','276732431')",{"id":i})
stop_t=time.time()
print("STOP:"+str(stop_t))
print(stop_t-start_t)
这是MySQL的测试脚本:
import MySQLdb
import time
conn=MySQLdb.connect(host="localhost",user="root",passwd="",db="test")
cur=conn.cursor()
conn.autocommit=True
start_t=time.time()
print("START:"+str(start_t))
for i in range(0,1000000):
cur.execute("insert into tt values(%s,%s,%s,%s,%s)",(i,"digoal.zhou",32,"digoal@126.com","276732431"))
stop_t=time.time()
print("STOP:"+str(stop_t))
print(stop_t-start_t)
统一建表脚本(这个脚本在oracle,mysql,pg都能跑):
create table tt(id int, username varchar(20), age int, email varchar(20), qq varchar(20))
mongodb测试结果(mongodb3.2.9windows版,pymongo):
297秒,比虚拟机的成绩要好,看来我这机器性能还是不错的^_^
由于机器上安装有oracle12.1,所以就来加入战局,DB大乱斗:
没想到测试结果竟然是368秒!附测试结果(python+cx_Oracle):
这下怎么解释啊,坦率地说,内心里面 对O偏爱>PG>mysql,但是被mysql实力打脸了^_^
分析oracle的原因,看来主要还是自动提交比较耗时,但问题是其他DB也是自动提交啊
plsql中,单次提交的效果,244秒与PG差不多:
改成批量提交后85秒:
不过如果oracle”火力全开“的话,最好成绩是1.28秒,当然,这个仅供参考,更公平的还是普通的写法:
在虚拟机上,用python测试插入100万记录竟然用了3001秒!暂时想不通原因,用plpgsql测试一把,只要5秒钟,找回了一点信心:
plpgsql代码:
create or replace function pgins2(num bigint) returns bigint AS $$
declare
ii integer;
beg_tm timestamp;
end_tm timestamp;
time_consuming bigint ;
begin
II:=1;
beg_tm:=now();
FOR ii IN 1..num LOOP
insert into tt values(ii,'digoal.zhou',32,'digoal@126.com','276732431');
end loop;
end_tm:=now();
select round(EXTRACT(EPOCH from end_tm)-EXTRACT(EPOCH from beg_tm)) into time_consuming;
return time_consuming;
end;
$$ LANGUAGE plpgsql;
2017-02-21更新:
再次在虚拟机上测试了PG9.2.8与最新的9.6.2正式版,如果自动提交打开的话,都需要2500多秒,而在同一台机上,mariadb只要159秒;
但当把自动提交关掉,变成插入后一次提交之后,PG9.6也只用了129秒:
这才是比较正常的结果,为什么虚拟机上与物理机在自动提交模式上差异这么大,也许跟PG的事务特性有关;
为了公平起见,又对maria_db的脚本也去掉了自动提交,再跑了一次:
感觉mariadb对于自动提交与非自动提交并没有太大的差别,也许本身就作了优化吧;
总而言之,我觉得PG与MYSQL的表现都很好了;