Проблема производительности пакетной вставки postgresql (в отношении mysql) - PullRequest
2 голосов
/ 20 января 2011

У меня много данных, и я хочу вставить их в БД хотя бы раз. Я делаю некоторые тесты. Я создаю таблицу (используя скрипт ниже * 1) с 21 столбцом. 1 столбец является целым, остальные 20 столбцов являются строковыми. Там нет индекса. Я пишу тестовый код, создаю случайные значения и вставляю в БД (используя вставку sql * 2). Прежде чем запускать команду sql, вызовите conn.setAutoCommit (false), чем conn.commit (). Эта операция около 6-7 секунд. Существует официальный документ (* 3), в котором говорится, что для массовой вставки используется команда «COPY». Создайте аналогичный файл ascii и повторно протестируйте его, этот тест закончился примерно за 5 секунд. Используя тот же тестовый код на той же машине, вставьте те же данные в Mysql, тестируйте менее 1 секунды. Я действительно удивляюсь, что по сравнению с 6-7 секундами большое улучшение производительности. Это различие действительно существует, или я что-то упускаю.

Спасибо за помощь

Моя тестовая конфигурация - это Solaris 10 и PostgreSQL 9.0.2 и Mysql 5.0.85.

(* 1) PostgreSQL Create DB Script

CREATE TABLE tablo
(
  id integer,
  column1 character varying(50),
  column2 character varying(50),
  column3 character varying(50),
  ....
  column20 character varying(50)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE tablo OWNER TO pgadmin;

(* 2) Вставить запрос

INSERT INTO tablo values (1,'column67062724628797','column26007603757271','column73982294239806','column43213154421324','column97722282440805','column79000889379973','column10680880337755','column14322827996050','column80720842739399','column22777514445036','column77771307997926','column92799724462613','column89992937353110','column61693061355353','column43804223262229','column62209656630047','column52150955786400','column85726157993572','column33358888005133','column77743799989746'),(2,'column77383691774831','column67841193885377','column36149612452454','column51161680852595','column91649734476301','column57283307765550','column14997046117948','column29457857794726','column91157683305554','column44413196495111','column40702778794938','column24744999726868','column38356057278249','column16808618337554','column64362413535503','column19577167594144','column72943639162993','column46830376244427','column01942608599939','column66479131355003'),
....
10K lines

(* 3) Официальный адрес документа PostgreSql http://www.postgresql.org/docs/8.3/interactive/populate.html

Ответы [ 3 ]

5 голосов
/ 20 января 2011

Кажется странным, что вы не видите ускорения с такими вещами, как использование COPY. Я сгенерировал скрипт для создания похожей таблицы и заполнил ее 10000 строками и обнаружил, что:

  1. Самый медленный: 1 строка на вставку, без блока транзакции, fsync = on
  2. Быстрее: обернуть все операторы (создать таблицу, вставить ....) в транзакцию
  3. Та же скорость, что и у 2: как 1, но выключить fsync = 100 * *
  4. Самый быстрый: восстановление с использованием скрипта, созданного pg_dump, для заполнения таблицы с помощью COPY

Методы 2 и 3 были примерно в 4 раза быстрее, чем метод 1. Метод 4 был примерно в 10 раз быстрее, чем 2 или 3.

Если я импортирую те же данные в mysql на моем компьютере, это займет примерно половину времени, как методы 2 или 3. То же самое. Сбрасывать с -e и перезагружать, тоже самое. Использование InnoDB увеличило время до того же уровня, что и методы 2 или 3.

Так что, по крайней мере, в моей комбинации оборудования / ОС скорости между ними сравнимы ... хотя, конечно, я лучше присматриваюсь к настройкам postgresql, но для такой маленькой таблицы, как эта, я бы не ожидал таких вещей, как размер кеша буфера иметь большое значение?

Теперь о том, насколько хороша поддержка JDBC для пакетной вставки, я понятия не имею. Я сделал все это, используя только клиенты командной строки.

2 голосов
/ 20 января 2011

Здесь есть два основных момента:

  1. mysql предназначен для скорости по сравнению со всем остальным, postgres - нет, тип таблицы mysql по умолчанию даже не обрабатывает транзакции ... эти дополнительные функции, поддерживаемые postgres, могут в некоторых ситуациях добавлять дополнительные издержки, чтобы сделать их возможными. ..
  2. Это не очень распространенный вариант использования - одновременная вставка 10000 записей крайне редка в большинстве приложений. Что более распространено, так это одновременная вставка небольших порций данных из разных соединений. В этом случае postgres использует блокировку на уровне строк - функция, не поддерживаемая типом таблицы mysql по умолчанию, что (по крайней мере теоретически) должно привести к тому, что она превосходит mysql. *

Итак, если массовые вставки из одного соединения не являются нормой для вашего приложения, этот тест действительно не показывает ничего полезного ... Скорее всего, вы будете использовать десятки соединений одновременно для вставки, запроса и / или обновить небольшие порции данных

0 голосов
/ 01 сентября 2011
  1. создание родительской таблицы без индекса, только столбец и типы там (создать таблицу some_data (c_1 int, c_2 varchar, ....))
  2. создать последовательность для перечисления новых таблиц данных
  3. взять новый идентификатор из последовательности
  4. создать новую таблицу для реальных данных с ключевым словом 'like' (создать таблицу some_data_X like some_data)
  5. вставить реальные данные в some_data_X с копией в двоичном формате
  6. создание индексов, ограничений (расширение возможностей ваших ядер с помощью нескольких соединений для postgresql)
  7. наследование родительской таблицы
  8. теперь готово к выбору!

Втаким образом я достиг 400000-500000 вставок в секунду с созданием индекса на 10 столбцах (2 xeon, 24 ядра, 24 Гб памяти, SSD).

  1. Бонус: в отдельном потоке удалить старые данные (some_data_X с min X): огромный круговой буфер с индексацией!
...