Postgres vs oracle做了100万平方米我做错了吗?

时间:2014-08-04 20:00:59

标签: sql database oracle postgresql amazon-web-services

我们试图了解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实例上运行的,我们在白天在不同日期运行了多次,结果始终相同

8 个答案:

答案 0 :(得分:2)

正如其他人所说,你的榜样测试毫无意义。

我认为您遇到的基本问题是您对PostgreSQL一无所知,并尝试使用与Oracle相同的基本技巧。

  

我们试图了解Oracle与PostgreSQL的原始性能

嗯那真的不是意味着是什么呢?除非你试图测量原始磁盘读取或其他一些。

  

我们已经尽可能地调整它们(检查所有参数改变随机页面成本,将seq扫描设置为关闭等)

好吧,将seq_scan设置为off除了在探索测试用例时强制规划器之外,不太可能是你想做的事情。是什么让你这样做的?它在手册中的哪个位置表明了它?你没有说 你如何改变了随机页面成本,也没有说你如何确定你有正确的价值。

  

我们发现,对于PostgreSQL,如果表格大于共享内存设置的25%,则表格数据不会被缓存。

嗯,这显然是不可能的。缓存发生在PostgreSQL和OS级别,磁盘块缓存。你是如何测量的?

  

(在我们的案例中,AWS 30 gig实例有一个7 gigs的共享内存,一旦我们得到2gig的表大小,它就会再次开始缓存)

那么你如何评估shared_mem呢?我试图想象一个场景,2G和7G都是合理的值,我遇到了麻烦。您没有提供任何内存使用信息,因此没有人可以知道发生了什么。

我认为您需要做的是以下内容:

  1. 喝一杯热茶/咖啡。
  2. 通读manuals
  3. 浏览维基,例如Tuning Your PostgreSQL Server
  4. 一旦你对work-mem和shared-mem操作方式有了合理的把握,就可以在服务器上进行一些测量,这样你就可以看到内存使用情况,磁盘I / O等。
  5. 确保您basic understanding查询EXPLAIN ANALYZE {。}}。{/ li>
  6. 订阅其中一个postgresql.org邮件列表(表现似乎有道理),所以你可以在某个地方进行讨论。
  7. 然后开始考虑测量性能。
  8. 的情况下Oracle会比PostgreSQL更聪明,但是一般的全面主要减速并不是你期望看到的。

答案 1 :(得分:1)

这是一种猜测。在这样的计算中,我希望Oracle比Postgres慢。但是,我认为您可能遇到documentation中的性能问题:

  

数字类型可以存储具有大量数字的数字   并完全执行计算。特别推荐   存储金额和其他精确度的数量   需要。但是,比较数值的算术非常慢   整数类型,或者描述的浮点类型   下一节。

您的代码未声明f的数据类型。通过上下文,它将被指定为整数。但是,sqrt()函数采用浮点或numeric常量。这些并不等同(我猜测当numeric时,函数更慢)。我的猜测是整数f转换为number而不是real进行操作。

尝试通过明确声明freal或在函数调用之前将其强制转换来运行测试。这可能会提高绩效。

答案 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作为一个止损。

毫无疑问,写作比我将要提供的更好,但是从新手的角度来看:

我想念甲骨文的事情:

  • 操作系统身份验证(允许用户根据其Windows / Unix凭据登录的能力),没有杂乱的密码问题
  • "合并"声明
  • 通过OCI(ODP.net,DBD :: Oracle)批量插入和更新
  • 部分通过程序提交的能力
  • 可用的IDE(如All Around Automation PL / SQL Developer)
  • 位图索引
  • 更无缝的DBlinks

我喜欢PostgreSQL:

  • 价格标签
  • "拷贝"比SQL * Loader
  • 更容易使用
  • ODBC和Npgsql.dll for .NET等驱动程序的可用性
  • SQL内部的自定义函数不会降低查询性能
  • 使用PL以外的语言创建自定义函数的能力(即Perl)
  • 更容易使用数据类型,例如日期,时间,时间戳和间隔
  • 一种边界直观的更新语法(并且不需要额外存在的包装器)

同样,我远离专家。这两个数据库平台都很高兴能够使用并处理如此繁重的工作。

- 编辑 -

我应该补充一点,直到今天我还没想出如何在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秒。

故事的寓意是你需要注意你正在使用的数据类型。