PostgreSQL VS Oracle OLTP 的测试方法 - 2

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:
本文主要是针对Oracle的测试, PostgreSQL的测试和测试结果请参考上一篇:
http://blog.163.com/digoal@126/blog/static/163877040201541104656600/

Oracle版本为12c。硬件和软件环境与上一篇测试PostgreSQL的保持一致,同一台主机,测试时关闭其他任何有干扰的服务和软件。
调整Oracle参数,创建测试表,生成测试数据:
SQL> create tablespace tbs_digoal datafile '/data01/oradata/tbs_digoal' size 30G autoextend off;
SQL> create tablespace tbs_digoal_idx datafile '/data02/oradata/tbs_digoal_idx' size 30G autoextend off;

SQL> create user digoal identified by digoal default tablespace tbs_digoal;
SQL> grant resource,connect,dba to digoal;
SQL> grant unlimited tablespace to digoal;

SQL> alter system set processes=2000 scope=spfile;
SQL> alter system set SGA_TARGET=24G scope=spfile;
SQL> alter system set PGA_AGGREGATE_TARGET=1G scope=spfile;
SQL> alter system set db_keep_cache_size=10G scope=spfile;
SQL> alter system set CURSOR_SHARING=force scope=spfile;
SQL> alter system set commit_logging='batch' scope=spfile;  
SQL> alter system set commit_write='nowait' scope=spfile;

SQL> shutdown immediate
SQL> startup

SQL> conn digoal/digoal
SQL> create table tbl (id int,info varchar2(256),crt_time date) tablespace tbs_digoal;

插入测试数据:
declare   
id int := 1; 
begin   
loop   
exit when id>50000000; 
insert into digoal.tbl nologging select id,sysdate,sysdate from dual;
id := id+1;
end loop; 
commit;
end; 
/

-- 或
 
declare  
maxrecords constant int := 50000000; 
begin 
for id in 1..maxrecords loop 
insert into digoal.tbl nologging select id,sysdate,sysdate from dual;
end loop; 
dbms_output.put_line('成功导入数据!'); 
commit; 
end; 
/

-- 或
SQL> insert into digoal.tbl nologging select rownum,sysdate,sysdate from dual connect by level <=50000000;

创建主键,将数据加载到内存。
SQL> alter table digoal.tbl add constraint tbl_pkey primary key(id) using index tablespace tbs_digoal_idx;
SQL> alter table digoal.tbl storage (buffer_pool KEEP);
SQL> alter index digoal.tbl_pkey storage (buffer_pool KEEP);

修改profile
# vi /etc/profile
export ORACLE_BASE=/opt/oracle/product
export ORACLE_HOME=$ORACLE_BASE/12.0.2/db_1
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH
export PATH=$ORACLE_HOME/bin:$PATH

# . /etc/profile

安装python oracle驱动
# wget https://pypi.python.org/packages/source/c/cx_Oracle/cx_Oracle-5.1.3.tar.gz#md5=cd6ff16559cbc9c20087ec812c7092ab
# tar -zxvf cx_Oracle-5.1.3.tar.gz
# cd cx_Oracle-5.1.3
# python setup.py install

python测试脚本:
# vi test.py
import threading
import time
import cx_Oracle
import random

dsn=cx_Oracle.makedsn('127.0.0.1', 1521, 'oradb')

xs=12000
tps=dict()

class n_t(threading.Thread):   # The timer class is derived from the class threading.Thread
  def __init__(self, num):
    threading.Thread.__init__(self)
    self.thread_num = num

  def run(self): #Overwrite run() method, put what you want the thread do here
    db=cx_Oracle.connect('digoal','digoal',dsn)
    db.autocommit=1
    cur=db.cursor()
    pre=cur.prepare('update /*SQL' + str(self.thread_num) + '*/ tbl set info=sysdate,crt_time=sysdate where id=:id')

    tps[self.thread_num] = dict()

    f = open("/tmp/oracle_test." + str(self.thread_num), "w")

    for x in range(1,3001):
      start_t = time.time()
      for i in range(0,xs):
        cur.execute(pre,{'id':random.randrange(1,50000000)})    
      stop_t = time.time()
      tps[self.thread_num][x] = round(xs/(stop_t-start_t),2)
      res = "Round: " + str(x) + " TID: " + str(self.thread_num) + " Sec: " + str(round((stop_t-start_t),2)) + " tps: " + str(tps[self.thread_num][x])
      print >> f, res
      f.flush()

    f.close()

def test():
  t_names = []
  for i in xrange(0,26):
    t_names.append(n_t(i))

  for t in t_names:
    t.start()
  
  return

if __name__ == '__main__':
  test()

更新(26 conn)测试:
# nohup python ./test.py >/dev/null 2>&1 &
测试结果,约10秒输出一次tps:
# less /tmp/oracle_test.22
Round: 1 TID: 22 Sec: 11.46 tps: 1187.12
Round: 2 TID: 22 Sec: 11.34 tps: 1198.65
.....
其他线程结果略。

测试结果合并:
# vi tps.py
import fileinput

file = dict()
line = dict()
tps=0

for i in xrange(0,26):
  file[i] = open("/tmp/oracle_test." + str(i))
 
while 1:
    for i in xrange(0,26):
      line[i] = file[i].readline().split(" ",8)[7]
      tps = tps + float(line[i])

    print(str(tps))
    tps=0

    if not line[0]:
      break
      
for i in xrange(0,26):
  file[i].close()

# python tps.py
33792.57
29093.92
33370.67
33768.3
33750.5
33458.86
30580.32
33369.79
......
图1:
Oracle UPDATE TPS集中在32000到33000,比较平顺。

查询(36 conn)测试:
测试脚本:
# vi test.py
import threading
import time
import cx_Oracle
import random

dsn=cx_Oracle.makedsn('127.0.0.1', 1521, 'oradb')

xs=12000
tps=dict()

class n_t(threading.Thread):   # The timer class is derived from the class threading.Thread
  def __init__(self, num):
    threading.Thread.__init__(self)
    self.thread_num = num

  def run(self): #Overwrite run() method, put what you want the thread do here
    db=cx_Oracle.connect('digoal','digoal',dsn)
    db.autocommit=1
    cur=db.cursor()
    pre=cur.prepare('select /*SQL' + str(self.thread_num) + '*/ * from tbl where id=:id')

    tps[self.thread_num] = dict()

    f = open("/tmp/oracle_test." + str(self.thread_num), "w")

    for x in range(1,3001):
      start_t = time.time()
      for i in range(0,xs):
        cur.execute(pre,{'id':random.randrange(1,50000000)})    
      stop_t = time.time()
      tps[self.thread_num][x] = round(xs/(stop_t-start_t),2)
      res = "Round: " + str(x) + " TID: " + str(self.thread_num) + " Sec: " + str(round((stop_t-start_t),2)) + " tps: " + str(tps[self.thread_num][x])
      print >> f, res
      f.flush()

    f.close()

def test():
  t_names = []
  for i in xrange(0,36):
    t_names.append(n_t(i))

  for t in t_names:
    t.start()
  
  return

if __name__ == '__main__':
  test()
测试结果:
# less oracle_test.0
Round: 1 TID: 0 Sec: 13.37 tps: 897.85
Round: 2 TID: 0 Sec: 11.72 tps: 1023.83
Round: 3 TID: 0 Sec: 11.89 tps: 1009.26
Round: 4 TID: 0 Sec: 11.82 tps: 1015.2
Round: 5 TID: 0 Sec: 11.84 tps: 1013.37
Round: 6 TID: 0 Sec: 11.91 tps: 1007.87
Round: 7 TID: 0 Sec: 11.97 tps: 1002.33
Round: 8 TID: 0 Sec: 11.96 tps: 1003.0
Round: 9 TID: 0 Sec: 11.92 tps: 1007.11
Round: 10 TID: 0 Sec: 11.75 tps: 1020.97
Round: 11 TID: 0 Sec: 11.75 tps: 1021.17
Round: 12 TID: 0 Sec: 11.95 tps: 1004.07
Round: 13 TID: 0 Sec: 11.81 tps: 1015.96
......
合并结果:
36637.71
36436.34
36512.47
36614.69
36585.26
36553.55
36578.89
36540.29
36483.53
36594.29
36438.53
36518.64
36480.38
......
图2:

插入(20 conn)测试:
SQL> truncate table digoal.tbl;
SQL> create sequence digoal.seq cache 12000;
SQL> alter table digoal.tbl modify crt_time default sysdate;
SQL> alter table digoal.tbl modify info default sysdate;
SQL> alter table digoal.tbl storage (buffer_pool default);
SQL> alter index digoal.tbl_pkey storage (buffer_pool default);
测试脚本:
# vi test.py
import threading
import time
import cx_Oracle
import random

dsn=cx_Oracle.makedsn('127.0.0.1', 1521, 'oradb')

xs=12000
tps=dict()

class n_t(threading.Thread):   # The timer class is derived from the class threading.Thread
  def __init__(self, num):
    threading.Thread.__init__(self)
    self.thread_num = num

  def run(self): #Overwrite run() method, put what you want the thread do here
    db=cx_Oracle.connect('digoal','digoal',dsn)
    db.autocommit=1
    cur=db.cursor()
    pre=cur.prepare('insert /*SQL' + str(self.thread_num) +'*/ into tbl (id) values(seq.nextval)')

    tps[self.thread_num] = dict()

    f = open("/tmp/oracle_test." + str(self.thread_num), "w")

    for x in range(1,3001):
      start_t = time.time()
      for i in range(0,xs):
        cur.execute(pre)    
      stop_t = time.time()
      tps[self.thread_num][x] = round(xs/(stop_t-start_t),2)
      res = "Round: " + str(x) + " TID: " + str(self.thread_num) + " Sec: " + str(round((stop_t-start_t),2)) + " tps: " + str(tps[self.thread_num][x])
      print >> f, res
      f.flush()

    f.close()

def test():
  t_names = []
  for i in xrange(0,20):
    t_names.append(n_t(i))

  for t in t_names:
    t.start()
  
  return

if __name__ == '__main__':
  test()
测试结果:
# less oracle_test.19
Round: 1 TID: 19 Sec: 22.98 tps: 522.25
Round: 2 TID: 19 Sec: 27.12 tps: 442.54
Round: 3 TID: 19 Sec: 23.8 tps: 504.2
Round: 4 TID: 19 Sec: 26.47 tps: 453.35
Round: 5 TID: 19 Sec: 23.63 tps: 507.83
Round: 6 TID: 19 Sec: 23.78 tps: 504.72
Round: 7 TID: 19 Sec: 26.02 tps: 461.13
Round: 8 TID: 19 Sec: 23.9 tps: 502.02
Round: 9 TID: 19 Sec: 26.22 tps: 457.67
Round: 10 TID: 19 Sec: 23.48 tps: 511.14
Round: 11 TID: 19 Sec: 26.89 tps: 446.31
Round: 12 TID: 19 Sec: 22.46 tps: 534.37
......
合并结果:
10195.18
8863.84
10067.91
9167.06
9753.85
10024.51
9028.92
10006.42
8869.49
10251.39
9202.53
10048.2
10062.34
......
图3:
Oracle插入时需先写UNDO,再写redo,所以比较慢.

[其他]
1. 一开始测试脚本报错,ORA-24550 KPEDBG_HDL_PUSH_FCPTRMAX。
解决办法 : 
# cd /opt/oracle/product/12.0.2/db_1/network/admin/
# cp samples/sqlnet.ora ./
# vi sqlnet.ora
追加 : 
DIAG_ADR_ENABLED=FALSE
DIAG_SIGHANDLER_ENABLED=FALSE
DIAG_DDE_ENABLED=FALSE
2. 测试时遇到过大量的CURSOR pin S的等待事件,通过添加注释,改写SQL解决。
例如:
    pre=cur.prepare('insert /*SQL' + str(self.thread_num) +'*/ into tbl (id) values(seq.nextval)')
[参考]
1. http://blog.163.com/digoal@126/blog/static/163877040201541104656600/

图1
6597243489496061228
图2
6608833441562599399
图3
6630910535536760470

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
6天前
|
人工智能 测试技术 开发者
北大李戈团队提出大模型单测生成新方法,显著提升代码测试覆盖率
【9月更文挑战第27天】北京大学李戈团队在人工智能领域取得重要突破,提出HITS新方法,通过将待测方法分解为多个切片并利用大型语言模型逐个生成测试用例,显著提升代码测试覆盖率,尤其在处理复杂方法时效果显著,为软件开发和测试领域带来新希望。尽管存在一定局限性,HITS仍展示了巨大潜力,未来有望克服限制,推动软件测试领域的创新发展。论文详情见【https://www.arxiv.org/pdf/2408.11324】。
20 6
|
19天前
|
存储 Oracle 关系型数据库
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
从基本特性、技术选型、字段类型、事务提交方式、SQL语句、分页方法等方面对比Oracle和MySQL的区别。
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
|
3天前
|
Oracle NoSQL 关系型数据库
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
12 2
|
4天前
|
机器学习/深度学习 人工智能 安全
软件测试中的探索性测试:一种高效发现软件缺陷的方法
本文将深入探讨软件测试中的一种关键方法——探索性测试。探索性测试是一种动态的、探索性的软件测试方法,它依赖于测试人员的直觉和经验,通过实际操作软件来发现潜在的问题和缺陷。与传统的基于预定义用例的测试方法相比,探索性测试更加灵活,能够更全面地覆盖软件的各个方面,从而更有效地发现难以预见的错误和漏洞。
|
6天前
|
小程序 测试技术 程序员
『软件工程12』软件工程实践方法——软件测试
该文章详细阐述了软件测试的重要性和基本原则,并按测试阶段顺序介绍了单元测试、集成测试、确认测试以及系统测试的具体内容和实施步骤。
『软件工程12』软件工程实践方法——软件测试
|
6天前
|
测试技术 程序员 C语言
『软件测试4』耗子尾汁!2021年了,你还不知道这4种白盒测试方法吗?
该文章深入介绍了四种常用的白盒测试方法,包括语句覆盖、判定覆盖、条件覆盖以及路径覆盖,并探讨了这些方法在软件测试中的应用。
『软件测试4』耗子尾汁!2021年了,你还不知道这4种白盒测试方法吗?
|
11天前
|
测试技术 UED
软件测试中的探索性测试:一种有效的缺陷检测方法
探索性测试,作为一种灵活且强大的软件测试技术,越来越受到测试人员的青睐。它不仅依赖于预定义的测试用例,而是依靠测试人员的经验和直觉,动态地探索软件以发现缺陷。本文将深入探讨探索性测试的核心概念、优势以及如何在现代软件测试中有效应用这一方法。通过具体实例和实践技巧,我们将揭示如何利用探索性测试提高软件质量和测试效率。
17 4
|
20天前
|
Devops jenkins 测试技术
敏捷测试价值观、方法和实践读书笔记(10)
本文介绍了敏捷测试的延伸实践,重点讨论了持续集成(CI)和持续部署(CD)的概念与实践方法。持续集成强调频繁提交代码至主干并自动化构建测试,确保快速反馈和高质量代码。持续部署则进一步实现自动化部署,通过蓝绿部署、金丝雀发布等方式提升软件交付效率。此外,文章还探讨了持续反馈机制,如A/B测试和混沌工程,以及DevOps文化下的测试策略,强调测试在整个开发流程中的重要性。
27 0
敏捷测试价值观、方法和实践读书笔记(10)
|
20天前
|
XML 存储 API
敏捷测试价值观、方法和实践读书笔记(8)
本文介绍了API的基础知识,区分了Web Service和Web API的概念,详细阐述了Web Service中的SOAP服务和REST服务的特点及区别。同时,文章还探讨了如何在项目中进行API测试,包括API测试的类型和实施阶段,强调了API在现代软件开发中的重要性和优势。
8 0
敏捷测试价值观、方法和实践读书笔记(8)
|
6天前
|
机器学习/深度学习 Web App开发 测试技术
『软件测试3』八大典型的黑盒测试方法已来袭,快快接住!
该文章介绍了八种常用的黑盒测试方法,包括等价类划分、边界值分析、错误推测法、因果图法、决策表测试、状态转换法、场景法以及随机测试,并提供了相应的案例说明。

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版
  • 推荐镜像

    更多
    下一篇
    无影云桌面