我需要一个真正的 DBA 的意见。Postgres 8.3 在我的 Macbook Pro 上执行此查询需要 200 毫秒,而 Java 和 Python 在 20 毫秒(350,000 行)内执行相同的计算:
SELECT count(id), avg(a), avg(b), avg(c), avg(d) FROM tuples;
这是使用 SQL 数据库时的正常行为吗?
架构(该表包含对调查的回复):
CREATE TABLE tuples (id integer primary key, a integer, b integer, c integer, d integer);
\copy tuples from '350,000 responses.csv' delimiter as ','
我在 Java 和 Python 中为上下文编写了一些测试,它们粉碎了 SQL(纯 python 除外):
java 1.5 threads ~ 7 ms
java 1.5 ~ 10 ms
python 2.5 numpy ~ 18 ms
python 2.5 ~ 370 ms
即使 sqlite3 与 Postgres 竞争,尽管它假设所有列都是字符串(相比之下:即使在 Postgres 中仅使用切换到数字列而不是整数也会导致 10 倍的减速)
我尝试过但没有成功的调整包括(盲目地遵循一些网络建议):
increased the shared memory available to Postgres to 256MB
increased the working memory to 2MB
disabled connection and statement logging
used a stored procedure via CREATE FUNCTION ... LANGUAGE SQL
所以我的问题是,我在这里的体验是否正常,这就是我在使用 SQL 数据库时可以期待的吗?我可以理解 ACID 必须付出代价,但在我看来这有点疯狂。我不是要求实时游戏速度,但由于 Java 可以在 20 毫秒内处理数百万次双打,我感到有点嫉妒。
有没有更好的方法以便宜的方式进行简单的 OLAP(无论是在资金方面还是在服务器复杂性方面)?我研究过 Mondrian 和 Pig + Hadoop,但对维护另一个服务器应用程序并不太兴奋,也不确定它们是否会有所帮助。
没有 Python 代码和 Java 代码可以说是在内部完成所有工作。我只生成了 4 个数组,每个数组有 350,000 个随机值,然后取平均值。我不包括时间中的生成,只包括平均步骤。java 线程计时使用 4 个线程(每个数组平均一个),过大但绝对是最快的。
sqlite3 计时由 Python 程序驱动,并从磁盘运行(不是:内存:)
我意识到 Postgres 在幕后做了更多工作,但大部分工作对我来说并不重要,因为这是只读数据。
Postgres 查询不会更改后续运行的时间。
我重新运行了 Python 测试,包括将其从磁盘中脱机。时间大大减慢到近 4 秒。但我猜 Python 的文件处理代码几乎是用 C 语言编写的(尽管可能不是 csv lib?)所以这向我表明 Postgres 也没有从磁盘流式传输(或者你是正确的,我应该低头在谁写了他们的存储层之前!)