我们试图了解Oracle与PostgreSQL的原始性能。我们有丰富的oracle经验,但对PostgreSQL来说是新手。我们将使用我们的数据等运行大量查询。但首先,我们想要了解它们在基本内核任务上的表现,即数学和分支,因为SQL建立在它之上。
在AWS RDS中,我们创建了两个db.m3.2xlarge实例,其中包含oracle 11.2.0.4.v1许可证,另一个包含PostgreSQL(9.3.3)
我们都运行了100万平方根(从1到1毫米)的代码。然后在If..Then语句中做同样的事情。
结果有点令人不安:
Oracle 4.8 seconds
PostgreSQL 21.803 seconds
添加if语句:
Oracle 4.78 seconds
PostgreSQL 24.4 seconds
代码 Oracle平方根
SET SERVEROUTPUT ON
SET TIMING ON
DECLARE
n NUMBER := 0;
BEGIN
FOR f IN 1..10000000
LOOP
n := SQRT (f);
END LOOP;
END;
的PostgreSQL
DO LANGUAGE plpgsql $$ DECLARE n real;
BEGIN
FOR f IN 1..10000000 LOOP
n = SQRT (f);
END LOOP;
RAISE NOTICE 'Result => %',n;
END $$;
oracle添加if
SET SERVEROUTPUT ON
SET TIMING ON
DECLARE
n NUMBER := 0;
BEGIN
FOR f IN 1..10000000
LOOP
if 0 =0 then
n := SQRT (f);
end if;
END LOOP;
postgres添加if
DO LANGUAGE plpgsql $$ DECLARE n real;
BEGIN
FOR f IN 1..10000000 LOOP
if 0=0 then
n = SQRT (f);
end if;
END LOOP;
RAISE NOTICE 'Result => %',n;
END $$;
我为PostgreSQL使用了一个匿名块。我也把它做成了一个功能,得到了相同的结果
CREATE OR REPLACE FUNCTION testpostgrescpu()
RETURNS real AS
$BODY$
declare
n real;
BEGIN
FOR f IN 1..10000000 LOOP
n = SQRT (f);
END LOOP;
RETURN n;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION testpostgrescpu()
OWNER TO xxx
基于我们所听到的PostgreSQL以及它在很多方面与Oracle的可比性,我们对结果感到吃惊。我们错误地编写了PostgreSQL吗?我们缺少什么,或者就是这样。
注意:一旦我们开始在Oracle和PostgreSQL中对完全相同的数据运行查询,我们就会看到类似的模式。在基本查询方面差别不大,但随着它们开始变得越来越复杂,Oracle的速度提高了3-5倍。
同样,这是在相同的AWS RDS实例上运行的,我们在白天在不同日期运行了多次,结果始终相同
答案 0 :(得分:2)
正如其他人所说,你的榜样测试毫无意义。
我认为您遇到的基本问题是您对PostgreSQL一无所知,并尝试使用与Oracle相同的基本技巧。
我们试图了解Oracle与PostgreSQL的原始性能
嗯那真的不是意味着是什么呢?除非你试图测量原始磁盘读取或其他一些。
我们已经尽可能地调整它们(检查所有参数改变随机页面成本,将seq扫描设置为关闭等)
好吧,将seq_scan设置为off除了在探索测试用例时强制规划器之外,不太可能是你想做的事情。是什么让你这样做的?它在手册中的哪个位置表明了它?你没有说 你如何改变了随机页面成本,也没有说你如何确定你有正确的价值。
我们发现,对于PostgreSQL,如果表格大于共享内存设置的25%,则表格数据不会被缓存。
嗯,这显然是不可能的。缓存发生在PostgreSQL和OS级别,磁盘块将缓存。你是如何测量的?
(在我们的案例中,AWS 30 gig实例有一个7 gigs的共享内存,一旦我们得到2gig的表大小,它就会再次开始缓存)
那么你如何评估shared_mem呢?我试图想象一个场景,2G和7G都是合理的值,我遇到了麻烦。您没有提供任何内存使用信息,因此没有人可以知道发生了什么。
我认为您需要做的是以下内容:
有 的情况下Oracle会比PostgreSQL更聪明,但是一般的全面主要减速并不是你期望看到的。
答案 1 :(得分:1)
这是一种猜测。在这样的计算中,我希望Oracle比Postgres慢。但是,我认为您可能遇到documentation中的性能问题:
数字类型可以存储具有大量数字的数字 并完全执行计算。特别推荐 存储金额和其他精确度的数量 需要。但是,比较数值的算术非常慢 整数类型,或者描述的浮点类型 下一节。
您的代码未声明f
的数据类型。通过上下文,它将被指定为整数。但是,sqrt()
函数采用浮点或numeric
常量。这些并不等同(我猜测当numeric
时,函数更慢)。我的猜测是整数f
转换为number
而不是real
进行操作。
尝试通过明确声明f
为real
或在函数调用之前将其强制转换来运行测试。这可能会提高绩效。
答案 2 :(得分:1)
除非您碰巧在pl / sql或pg pl / sql中进行大量计算,否则我无法看到这将是一个有用的指标。这无论如何都不是真正推荐的,可以在C中本机完成或通过调用Java类来完成。 Oracle可以在某些平台/版本上将pl / sql本地编译为c,因此这可能是您看到速度差异很大的原因之一。
数据库的速度更好地取决于它执行查询的能力,可能包括正确统计的连接或写入和更新数据。对于像Oracle和Postgres这样的数据库,在多用户和事务环境中执行此操作的SQL将是一个更好的测试,假设您有一个OLTP应用程序。据我所知,Postgres与甲骨文的竞争做得很好,但这取决于你的应用程序。
为了更好地描述和分析Oracle,我建议查看asktom https://asktom.oracle.com/论坛。我不确定postgres是否有任何与此相近的内容。
答案 3 :(得分:1)
老实说,你的基准是毫无意义的。
你计算了100万平方根并且立即扔掉了结果;根据您的优化设置,我希望编译器完全摆脱您的循环。
你应该至少将结果存储在某处或者将它们用于其他计算(例如通过计算总和)。
另外,我不同意你的陈述即。数学和分支,因为SQL建立在之上。 RDBMS做了很多事情,但有效地计算平方根肯定不是它的强项之一。如果你真的真的需要这种计算,那么将它从数据库中移出并使用某种专用软件会更有意义,例如: R 。
答案 4 :(得分:1)
我对这些基准感到有些惊讶,但我倾向于在理论上同意弗兰克施密特的观点。虽然我不会说它完全没有意义,但是#34;如果你要比较两个DBMS系统,我认为你想要的不仅仅是每个人如何进行数学运算。
为了它的价值,我几乎只在我的前雇主那里使用了Oracle。在我的新角色中,我们的主要DBMS是Sybase ASE,它缺少我习惯使用的许多工具,我们使用PostgreSQL作为一个止损。
毫无疑问,写作比我将要提供的更好,但是从新手的角度来看:
我想念甲骨文的事情:
我喜欢PostgreSQL:
同样,我远离专家。这两个数据库平台都很高兴能够使用并处理如此繁重的工作。
- 编辑 -
我应该补充一点,直到今天我还没想出如何在Oracle中做到这一点:
select * from pg_views
where definition like '%inventory.turns%'
答案 5 :(得分:1)
您没有执行任何PostgreSQL基准测试。
你真正做的是pl / pgsqlbenchmark。
您可以使用这些PostgreSQL language extensions中的任何一个来进行此测试,您可能会得到相当不同的结果。
有一个pl / pgsql解释器将执行您的代码。它默认与PostgreSQL一起安装。 欲了解更多信息:
使用pl / java可以运行JVM,运行shell。
答案 6 :(得分:0)
plpgsql
不是广泛优化的性能语言。
我不知道为什么我想要在数据库中的显式循环中计算1000万平方根,但如果我这样做,我会使用plperl
来完成它。
答案 7 :(得分:0)
这里的问题是类型转换。 PostgreSQL sqrt
函数定义为接受双精度(浮点)或数字。
所以在你的代码中发生的事情是整数被转换为float(快速)sqrt
的float版本,结果是从float转换为real(慢速)的类型。
要了解我在说什么,请尝试比较这两个代码示例的运行时间:
DO LANGUAGE plpgsql $$
DECLARE n real;
BEGIN
FOR f IN 1..10000000 LOOP
n = f::float;
END LOOP;
RAISE NOTICE 'Result => %',n;
END $$;
DO LANGUAGE plpgsql $$
DECLARE n float;
BEGIN
FOR f IN 1..10000000 LOOP
n = f::float;
END LOOP;
RAISE NOTICE 'Result => %',n;
END $$;
在我的机器上,第一个需要16秒,第二个只需3秒。
故事的寓意是你需要注意你正在使用的数据类型。