Мне нужно настоящее мнение DBA. Postgres 8.3 занимает 200 мс для выполнения этого запроса на моем Macbook Pro, в то время как 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 с замедлением 10x)
Настройки, которые я пробовал без успеха, включают (слепо следуя некоторым советам в Интернете):
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 потока (по одному для каждого массива), overkill, но это определенно самый быстрый.
Время sqlite3 управляется программой Python и работает с диска (не: память:)
Я понимаю, что Postgres делает гораздо больше за кулисами, но большая часть этой работы для меня не имеет значения, поскольку это данные только для чтения.
Запрос Postgres не изменяет сроки последующих прогонов.
Я перезапустил тесты Python, чтобы включить буферизацию с диска. Время замедляется значительно до почти 4 секунд. Но я предполагаю, что код обработки файлов Python в значительной степени зависит от C (хотя, может быть, и не csv lib?), Поэтому это указывает на то, что Postgres не передает потоки с диска (или что вы верны, и я должен поклониться до того, кто написал свой слой памяти!)