oracle – PL/SQL或替代方案的数值优化

我们需要做一些计算繁重的工作来连接Oracle数据库.到目前为止,我们已经在PL / SQL中进行了数值计算,并且很大程度上缺乏性能.

现在我们正在实施一个多级库存模型(https://www.researchgate.net/publication/222409130_Evaluation_of_time-varying_availability_in_multi-echelon_spare_parts_systems_with_passivation)由于问题的严重性,我更关注性能.

我用三种语言实现了部分算法:Fortran(90-2008符合gfortran),Excel中的VBA和PL / SQL,并围绕它进行了一百万次调用测试循环.即使使用binary_double数据类型和使用PLSQL_CODE_TYPE = NATIVE的本机编译(两者都会导致改进),下面的测试代码仍然需要37秒才能运行(Oracle XE 11.2).相比之下,VBA在同一硬件上占用16s和Fortran 1.6s.

虽然要求性能接近Fortran数字可能太过分了(虽然这显然是非常需要的)但我很惊讶即使是不起眼的VBA也会执行PL / SQL.

所以我的问题有两个部分:

>我还可以尝试在Oracle方面进一步提高性能吗?
>如果我们考虑放弃PL / SQL,我们应该考虑哪些替代方案来连接Oracle数据库?虽然接近Fortran速度的性能提升将使我们考虑在应用程序的交互式部分中引入一些繁重的工作,但是繁重的工作将以类似批处理的方式被称为相对较少.我首选的数值工作语言仍然是Fortran,因为它易于实现带有屏蔽的多维数组.

此外,虽然我不是直接批评我的源代码本身,但如果有人能发现任何我可以合并的明显优化,我将不胜感激.

函数timeebo是测试函数,我用双精度简单的selectebo调用它;在SQL Developer中.

create or replace FUNCTION gammln(
    x IN binary_double)
  RETURN binary_double
IS
  --Lanczos' approximation to the Log Gamma function
  gammln binary_double;
  ser binary_double;
  tmp binary_double;
BEGIN
  tmp := x + 5.5;
  tmp :=(x + 0.5) * Ln(tmp) - tmp;
  ser := 1.000000000190015;
  ser := ser + 76.18009172947146 /(x + 1.0) ;
  ser := ser - 86.50532032941677 /(x + 2.0) ;
  ser := ser + 24.01409824083091 /(x + 3.0) ;
  ser := ser - 1.231739572450155 /(x + 4.0) ;
  ser := ser + 1.208650973866179E-03 /(x + 5.0) ;
  ser := ser - 5.395239384953E-06 /(x + 6.0) ;
  RETURN tmp + Ln(2.5066282746310005 * ser / x) ;
END;
/
CREATE OR REPLACE FUNCTION PoissonDist(
    k      IN INTEGER,lambda IN binary_double)
  RETURN binary_double
IS
BEGIN
  RETURN Exp((k * Ln(lambda)) - lambda - gammln(k + 1)) ;
END;
/
CREATE OR REPLACE FUNCTION EBO(
    stock    IN pls_integer,pipeline IN binary_double,accuracy IN binary_double DEFAULT 0.0000000001)
  RETURN binary_double
IS
  i pls_integer;
  EBO binary_double;
  term binary_double;
  temp binary_double;
  PoissonVal binary_double;
  peaked BOOLEAN; --Flag the Poisson curve as having peaked
BEGIN
  EBO        := 0.0;
  IF(pipeline = 0.0) THEN
    RETURN EBO;
  END IF;
--Initialise
i            := 1;
peaked       := false;
PoissonVal   := PoissonDist(stock + 1,pipeline) ;         --Get p() value
IF(PoissonVal < accuracy AND floor(pipeline) > stock) THEN --If p() is very
  -- small...
  i          := floor(pipeline)   - stock;         --Revise i to just below peak of Poisson curve
  PoissonVal := PoissonDist(stock + i,pipeline) ; --Get p() value close to
  -- peak
  temp := PoissonVal *(pipeline / CAST(stock + i + 1 AS binary_double)) ; --
  -- Store poisson value just above peak
  LOOP
    term       := CAST(i AS binary_double) * PoissonVal;
    EBO        := EBO                         + term;
    i          := i                           - 1; --Work backwards
    PoissonVal := PoissonVal                  *(CAST(stock + i + 1 AS DOUBLE
    PRECISION)                                / pipeline) ; --Revise Poisson
    -- value for next time
    EXIT
  WHEN(term < accuracy OR i = 0) ;
  END LOOP;
  i          := 1 + floor(pipeline) - stock;
  PoissonVal := temp;
  peaked     := true;
END IF;
LOOP
  term       := CAST(i AS binary_double) * PoissonVal;
  EBO        := EBO                         + term;
  i          := i                           + 1;
  PoissonVal := PoissonVal                  *(pipeline / CAST(stock + i AS
  binary_double)) ; --Revise Poisson value for next time
  IF(CAST(stock + i AS binary_double) > pipeline) THEN
    peaked                              := true;
  END IF;
  EXIT
WHEN(term < accuracy AND peaked) ;
END LOOP;
IF(EBO < accuracy) THEN
  EBO := 0.0;
END IF;
RETURN EBO;
END;
/
CREATE OR REPLACE FUNCTION timeebo
  RETURN binary_double
IS
  i pls_integer;
  EBOVal binary_double;
  acc binary_double;
BEGIN
  acc := 0.0;
  FOR i IN 1..1000000
  LOOP
    EBOVal := EBO(500,CAST(i AS binary_double) / 1000.0) ;
    acc    := acc                                + EBOVal;
  END LOOP;
RETURN acc;
END;
这不是对OP问题的回答(但它是一个“概念证明”,用于展示他在PL / SQL中所做的事情是如何在普通SQL中完成的).我只使用答案格式,因为我将在下面做的不适合评论.

OP要求了解如何在纯SQL中完成无限级数的求和,达到所需的精度.我将举两个例子.

第一个例子:

具有正项的无限级数:e = sum [j = 0至infinity](1 / factorial(j)).从0到n之和的误差的平凡上限是添加到系列的最后一个项.下面的递归查询(需要Oracle 11.1或更高版本 – 实际上我编写它的方式是11.2,在声明中使用列名,但它可以很容易地改为11.1)计算精确到38位小数的e值(最大精度)在Oracle中可用). e的逆因子序列收敛得非常快;这只需要35步,在我的旧家用电脑上运行不到0.001秒(这只是带键盘的戴尔平板电脑).

编辑:呃!只有我可以发布e = 3.71828的东西!即使在递归查询中我添加了所有条件(包括1/0!),我从1开始求和而不是0.(现在更正,但在纠正之前有这个错误.)

with 
     rec ( j,s,next_term,err ) as (
       select  0,1,2
         from  dual
       union all
       select  j+1,s + next_term,next_term/(j+1),next_term
         from  rec
         where err > power(10,-38) and j < 1000000000
     )
select max(j) as steps,round(max(s),38) as e 
from   rec
;

STEPS                                         E
-----  ----------------------------------------
   35  2.71828182845904523536028747135266249776

第二个例子:

好的,现在让我们采取交替的序列(其中最后一个术语的绝对值总是误差的上限),让我们采取一个非常缓慢收敛的序列:

ln(2)= sum [j = 1到无穷大]((-1)^(j – 1)/ j)

下面的查询计算ln(2),精确到小数点后五位;在这里我们事先知道我们需要100,000步,而我的机器上的计算大约需要1.1秒. (请记住,这是一个非常缓慢融合的系列.)

with
     rec ( j,sgn ) as (
       select  0,1
         from  dual
       union all
       select  j+1,s + sgn / (j+1),-sgn
         from  rec
         where j <= 100000
     )
select 100000 as steps,round(s,5) as ln_2
from   rec
where  j = 100000
;

 STEPS     LN_2
------  -------
100000  0.69314

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读773次,点赞6次,收藏9次。【代码】c# json字符串转Oracle的insert into的小程序。
文章浏览阅读8.7k次,点赞2次,收藏17次。此现象一般定位到远端的监听服务来找问题,在远端查看监听服务状态(具体看下面的解决方案会详细呈现),服务是否开启,另外查看监听端点概要是否存在host未指向到计算名的,如无直接进入监听配置文件listener.ora内添加指向即可。2、查看监听服务状态 lsnrctl status,右边为远端端点状态,未添加host指向到计算名;1、本地及远端安装好Oracle并配置好连接,Oracle服务和监听已启动;1、远程Oracle数据库:Oracle11g R2。或者进入下述服务手动重启。,再进行远程连接即可。_ora-12541:tns:无监听程序
文章浏览阅读2.8k次。mysql脚本转化为oracle脚本_mysql建表语句转oracle
文章浏览阅读2.2k次。cx_Oracle报错:cx_Oracle DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library_cx_oracle.databaseerror: dpi-1047: cannot locate a 64-bit oracle client libr
文章浏览阅读1.1k次,点赞38次,收藏35次。本文深入探讨了Oracle数据库的核心要素,包括体系结构、存储结构以及各类参数。通过解析Oracle数据库的体系结构,读者可以深入了解其内部组成和工作原理。存储结构部分介绍了数据在Oracle中的存储方式,从表空间到数据文件的层层逻辑。最后,我们深入探讨了Oracle数据库中各类参数的作用和配置方法,帮助读者更好地理解和优化数据库性能。本文旨在帮助读者全面理解Oracle数据库的运作机制,为其在实践中的应用提供基础和指导。
文章浏览阅读1.5k次。默认自动收集统计信息的时间为晚上10点(周一到周五,4个小时),早上6点(周六,周日,20个小时)由于平时默认每天只收集4小时,时间有点短了,改成每天可收集8小时。oracle 18c中默认是打开的。查看当前自动收集统计信息的时间。_oracle自动收集统计信息
文章浏览阅读929次,点赞18次,收藏20次。只有assm(Automatic Shared Memory Management)模式可以使用大页,需要关闭amm(Memory Manager Process)HugePages_Free: 306 (空闲306页,已使用306-306=0页)防止oracle使用的内存交换,所以设置的大小与oracle配置的sga、pga相关。HugePages_Rsvd: 0 (操作系统承诺给oracle预留的页数)HugePages_Total: 306 (总共306页)_oracle11g 大页
文章浏览阅读801次。例如:10046:0,1,4,8,12。默认redo日志有三个,大小为50M,循环覆盖使用。redo log再覆盖之前,会被归档,形成归档日志。答:不同事件,不同级别。trace的不同级别?_oracle 日志
文章浏览阅读4.2k次,点赞84次,收藏77次。主要讲解MySQL中SQL的DDL语句,其中包括对数据库和表的一系列操作。_sql ddl 新增字段 mysql
文章浏览阅读1.1k次。ON DEMAND:仅在该物化视图“需要”被刷新了,才进行刷新(REFRESH),即更新物化视图,以保证和基表数据的一致性;ON COMMIT:一旦基表有了COMMIT,即事务提交,则立刻刷新,立刻更新物化视图,使得数据和基表一致。Method =>'C',物化视图有三种刷新方式:COMPLETE、FAST和FORCE。物化视图会占用空间,一半可用于大量数据查询时,减缓主表的查询压力使用。例如创建一个物化视图,让对接单位查询。_oracle物化视图定时刷新
文章浏览阅读713次,点赞21次,收藏18次。1.背景介绍在当今的大数据时代,数据量越来越大,传统的关系型数据库已经无法满足业务需求。因此,NoSQL数据库技术迅速崛起,成为企业和开发者的首选。Oracle NoSQL Database是Oracle公司推出的一款分布式NoSQL数据库产品,具有高性能、高可用性和易于扩展等特点。在本文中,我们将深入了解Oracle NoSQL Database的集成与开发者工具,帮助您更好地掌握这款产品的...
文章浏览阅读2.5k次,点赞2次,收藏4次。今天遇见一个问题需要将字段中包含中文字符串的筛选出来。_oracle查询包含中文字符
文章浏览阅读802次。arcmap 在oracle删除表重新创建提示表名存在解决放啊
文章浏览阅读4.3k次,点赞2次,收藏4次。Oracle连接数据库提示 ORA-12638:身份证明检索失败_ora-12638
文章浏览阅读3.4k次,点赞6次,收藏25次。etc/profile是一个全局配置文件,所有用户登录都会使用该文件构建用户环境。与windows配置环境变量是一个道理。选择Linux系统,找到适合自己系统的安装包,我的是CentOS 8 x64。接下来需要登陆Oracle账户才能下载,无账户的可以自己注册一个。Linux中export 命令用于设置或显示环境变量。模式,利用上下键到文档最后,添加以下代码。出现如图所示版本号字样,则说明安装成功。点击下载,勾选1,点击2。记住完整路径用于后面配置。找到Java并点击进去。往下翻,找到Java8。_linux安装jdk1.8
文章浏览阅读2.4w次,点赞26次,收藏109次。JDK 是的简称,也就是 Java 开发工具包。JDK 是整个 Java 的核心,其中JDK包含了 Java 运行环境(Java Runtime Envirnment,简称 JRE),Java 工具(比如 javac、java、javap 等等),以及 Java 基础类库(比如 rt.jar)。最主流的 JDK 是Oracle公司发布的 JDK,除了 Oracle JDK(商业化,更稳定)之外,还有很多公司和组织开发了属于自己的 JDK,比较有名的有IBM JDK(更适合 IBM) 和OpenJDK。_jdk安装教程
文章浏览阅读7.5w次。出现 “java.sql.SQLNonTransientConnectionException:Could not create connection to database server” 的错误通常是由于无法连接到数据库服务器引起的。_java.sql.sqlnontransientconnectionexception: could not create connection to
文章浏览阅读849次,点赞7次,收藏10次。在ClickHouse中创建用户、数据库并进行权限分配是一个重要的管理任务,它涉及到安全性和访问控制。下面是一个基本的指南来帮助你完成这些操作:1. 创建数据库首先,需要创建一个数据库。使用以下命令:CREATE DATABASE IF NOT EXISTS your_database_name;将 your_database_name 替换为你想要的数据库名。2. 创建用户接下来,创建一个新用户。使用以下命令:CREATE USER your_username IDENTIFIED WIT_在clickhouse中如何创建用户 赋权
文章浏览阅读1.2k次,点赞53次,收藏39次。本文是一篇关于Oracle数据库安装和使用的博文摘要。作者以轻松幽默的笔调介绍了自己在实验中掌握的Oracle数据库基本操作,包括使用组件查看命令、配置数据库监听器等。作者也分享了在实验中遇到的一些有趣问题,如SQL语句缺少分号导致的意外错误。此外,作者还强调了登录sys用户和启动实例加载数据库的注意事项,并鼓励读者面对挑战时保持乐观,不断提升自己的能力。整体风格风趣严谨,引人入胜。
文章浏览阅读820次,点赞17次,收藏16次。KingbaseES、xml、dbms_xmlgen、SETSKIPROWS、人大金仓、KingbaseES兼容Oracle包dbms_xmlgen的功能是通过SQL查询将关系表中数据转化为XML文档。转化方式一共有两种:(1)通过查询字符串直接转化。(2)通过上下文句柄转化。对于通过查询字符串直接转化的方式,无法跳过若干行进行查询,只能直接将表格中的所有数据转化为XML文档。