Низкая скорость вставки в табличное пространство памяти Postgresql - PullRequest
7 голосов
/ 28 мая 2010

У меня есть требование, когда мне нужно хранить записи со скоростью 10 000 записей в секунду в базе данных (с индексацией по нескольким полям). Количество столбцов в одной записи - 25. Я выполняю пакетную вставку 100 000 записей в одном блоке транзакции. Чтобы улучшить скорость вставки, я изменил табличное пространство с диска на оперативную память. Благодаря этому я могу достичь только 5000 вставок в секунду.

В конфиге postgres я также произвел следующую настройку:

  • Индексы: нет
  • fsync: false
  • протоколирование: отключено

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

  • Табличное пространство: RAM
  • Количество столбцов в одной строке: 25 (в основном целые числа)
  • Процессор: 4 ядра, 2,5 ГГц
  • RAM: 48 ГБ

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

Помощь оценена.

Prashant

Ответы [ 4 ]

16 голосов
/ 29 мая 2010

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

  1. Переведите ваши данные в CSV.
  2. Создайте временную таблицу (как вы заметили, без индексов).
  3. Выполнить команду COPY: \COPY schema.temp_table FROM /tmp/data.csv WITH 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 = 1GB
    temp_buffers = 32MB
    work_mem = 32MB
    maintenance_work_mem = 64MB
    seq_page_cost = 1.0
    random_page_cost = 2.0
    cpu_index_tuple_cost = 0.001
    effective_cache_size = 512MB
    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;

Не забудьте потом VACUUM и ANALYSE.

5 голосов
/ 28 мая 2010

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

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

или как одна многорядная вставка:

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

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

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

3 голосов
/ 28 мая 2010

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

1 голос
/ 28 мая 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...