Медленная скорость вставки в табличной области памяти Postgresql

У меня есть требование, где я должен сохранить записи по курсу 10 000 записей/секунда в базу данных (с индексацией на нескольких полях). Число столбцов в одной записи равняется 25. Я делаю пакетную вставку 100 000 записей в одном блоке транзакции. Для улучшения уровня вставки я изменил табличную область от диска до RAM.With, которого я могу достигнуть, только 5 000 вставляют в секунду.

Я также сделал следующее настраивание конфигурации пост-ГРЭС:

  • Индексы: нет
  • fsync: ложь
  • вход: отключенный

Другая информация:

  • Табличная область: RAM
  • Число столбцов в одной строке: 25 (главным образом целые числа)
  • ЦП: 4 ядра, 2,5 ГГц
  • ПОРШЕНЬ: 48 ГБ

Я задаюсь вопросом, почему единственный запрос на вставку занимает приблизительно 0,2 мс в среднем, когда база данных ничего не пишет на диске (поскольку я использую основанную на RAM табличную область). Есть ли что-то, что я делаю неправильно?

Help ценится.

Prashant

7
задан Milen A. Radev 28 May 2010 в 08:48
поделиться

4 ответа

Быстрая загрузка данных

  1. Переведите данные в CSV.
  2. Создайте временную таблицу (как вы заметили, без индексов).
  3. Выполните команду COPY: \ COPY schema.temp_table FROM /tmp/data.csv С CSV
  4. Вставьте данные в невременную таблицу.
  5. Создать индексы.
  6. Установите соответствующую статистику.

Дополнительные рекомендации

Для больших объемов данных:

  1. Разделите данные на дочерние таблицы.
  2. Вставьте его в порядке столбца, в котором будет использоваться большинство операторов SELECT . Другими словами, попытайтесь согласовать физическую модель с логической.
  3. Измените параметры конфигурации.
  4. Создайте индекс CLUSTER (самый важный столбец слева). Например:
    CREATE UNIQUE INDEX measurement_001_stc_index
      ON climate.measurement_001
      USING btree
      (station_id, taken, category_id);
    ALTER TABLE climate.measurement_001 CLUSTER ON measurement_001_stc_index;

Настройки конфигурации

На машине с 4 ГБ ОЗУ я сделал следующее ...

Конфигурация ядра

Сообщите ядру, что программы могут использовать большие объемы общей памяти:

sysctl -w kernel.shmmax=536870912
sysctl -p /etc/sysctl.conf

Конфигурация PostgreSQL

  1. Отредактируйте /etc/postgresql/8.4/main/postgresql.conf и установите:
    shared_buffers = 1 ГБ
    temp_buffers = 32 МБ
    work_mem = 32 МБ
    maintenance_work_mem = 64 МБ
    seq_page_cost = 1.0
    random_page_cost = 2.0
    cpu_index_tuple_cost = 0,001
    Effective_cache_size = 512 МБ
    checkpoint_segments = 10 
  2. Настройте значения по мере необходимости и в соответствии с вашей средой. Возможно, позже вам придется изменить их для подходящей оптимизации чтения / записи.
  3. Перезапустите PostgreSQL.

Дочерние таблицы

Например, у вас есть данные о погоде, разделенные на разные категории. Вместо того, чтобы иметь одну чудовищную таблицу, разделите ее на несколько таблиц (по одной на каждую категорию).

Основная таблица

CREATE TABLE climate.measurement
(
  id bigserial NOT NULL,
  taken date NOT NULL,
  station_id integer NOT NULL,
  amount numeric(8,2) NOT NULL,
  flag character varying(1) NOT NULL,
  category_id smallint NOT NULL,
  CONSTRAINT measurement_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);

Дочерняя таблица

CREATE TABLE climate.measurement_001
(
-- Inherited from table climate.measurement_001:  id bigint NOT NULL DEFAULT nextval('climate.measurement_id_seq'::regclass),
-- Inherited from table climate.measurement_001:  taken date NOT NULL,
-- Inherited from table climate.measurement_001:  station_id integer NOT NULL,
-- Inherited from table climate.measurement_001:  amount numeric(8,2) NOT NULL,
-- Inherited from table climate.measurement_001:  flag character varying(1) NOT NULL,
-- Inherited from table climate.measurement_001:  category_id smallint NOT NULL,
  CONSTRAINT measurement_001_pkey PRIMARY KEY (id),
  CONSTRAINT measurement_001_category_id_ck CHECK (category_id = 1)
)
INHERITS (climate.measurement)
WITH (
  OIDS=FALSE
);

Статистика таблицы

Увеличьте статистику таблицы для важных столбцов:

ALTER TABLE climate.measurement_001 ALTER COLUMN taken SET STATISTICS 1000;
ALTER TABLE climate.measurement_001 ALTER COLUMN station_id SET STATISTICS 1000;

Не забудьте ВАКУУМ и АНАЛИЗ ] после.

16
ответ дан 6 December 2019 в 07:05
поделиться

вы делаете вставку как серию

INSERT INTO tablename (...) VALUES (...);
INSERT INTO tablename (...) VALUES (...);
...

или как одно кратное -row insert:

INSERT INTO tablename (...) VALUES (...),(...),(...);

второй будет значительно быстрее на 100k строках.

источник: http://kaiv.wordpress.com/2007/07/19/faster-insert-for-multiple-rows/

5
ответ дан 6 December 2019 в 07:05
поделиться

Я предлагаю вам использовать COPY вместо INSERT .

Вам также следует настроить ваш файл postgresql.conf.

Читайте о http://wiki.postgresql.org/wiki/Performance_Optimization

1
ответ дан 6 December 2019 в 07:05
поделиться

Вы поместили xlog (сегменты WAL) также на RAM-диск? Если нет, то вы все еще пишете на диск. А как насчет настроек wal_buffers, checkpoint_segments и т.д. ? Вы должны попытаться получить все ваши 100 000 записей (ваша одна транзакция) в ваших wal_buffers. Увеличение этого параметра может привести к тому, что PostgreSQL запросит больше общей памяти System V, чем позволяет конфигурация по умолчанию вашей операционной системы.

3
ответ дан 6 December 2019 в 07:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: