7

我有一个要求,我需要以 10,000 条记录/秒的速度将记录存储到数据库中(在几个字段上建立索引)。一条记录中的列数为 25。我正在一个事务块中批量插入 100,000 条记录。为了提高插入率,我将表空间从磁盘更改为 RAM。这样我每秒只能实现 5,000 次插入。

我还在 postgres 配置中进行了以下调整:

  • 索引:没有
  • 同步:假
  • 记录:禁用

其他信息:

  • 表空间:内存
  • 一行中的列数:25(主要是整数)
  • CPU : 4 核, 2.5 GHz
  • 内存:48 GB

我想知道为什么当数据库没有在磁盘上写入任何内容时(因为我使用基于 RAM 的表空间),单个插入查询平均需要大约 0.2 毫秒。有什么我做错了吗?

帮助表示赞赏。

普拉尚

4

4 回答 4

16

快速数据加载

  1. 将您的数据转换为 CSV。
  2. 创建一个临时表(如您所述,没有索引)。
  3. 执行复制命令:\COPY schema.temp_table FROM /tmp/data.csv WITH CSV
  4. 将数据插入到非临时表中。
  5. 创建索引。
  6. 设置适当的统计数据。

进一步的建议

对于大量数据:

  1. 将数据拆分为子表。
  2. SELECT按照大多数语句将使用的列的顺序插入它。换句话说,尝试将物理模型与逻辑模型对齐。
  3. 调整您的配置设置。
  4. 创建一个CLUSTER索引(左侧最重要的列)。例如:
    创建唯一索引 measure_001_stc_index
      ONclimate.measurement_001
      使用 btree
      (station_id, 采取, category_id);
    ALTER TABLEclimate.measurement_001 CLUSTER ON measure_001_stc_index;

配置设置

在具有 4GB RAM 的机器上,我做了以下...

内核配置

告诉内核程序可以使用共享内存块:

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

PostgreSQL 配置

  1. 编辑/etc/postgresql/8.4/main/postgresql.conf和设置:
    shared_buffers = 1GB
    临时缓冲区 = 32MB
    工作内存 = 32MB
    维护工作内存 = 64MB
    seq_page_cost = 1.0
    random_page_cost = 2.0
    cpu_index_tuple_cost = 0.001
    有效缓存大小 = 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;

不要忘记VACUUMANALYSE之后。

于 2010-05-28T20:12:14.240 回答
5

你在做你的插入作为一系列

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

或作为一个多行插入:

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

第二个在 100k 行上会明显更快。

来源: http: //kaiv.wordpress.com/2007/07/19/faster-insert-for-multiple-rows/

于 2010-05-28T06:41:07.803 回答
3

您是否也在 RAM 驱动器上放置了 xlog(WAL 段)?如果没有,您仍在写入磁盘。那么 wal_buffers、checkpoint_segments 等的设置呢?您必须尝试在 wal_buffers 中获取所有 100,000 条记录(您的单笔交易)。增加此参数可能会导致 PostgreSQL 请求的 System V 共享内存超出操作系统默认配置所允许的数量。

于 2010-05-28T07:16:36.747 回答
1

我建议你使用COPY而不是INSERT.

您还应该微调您的 postgresql.conf 文件。

阅读http://wiki.postgresql.org/wiki/Performance_Optimization

于 2010-05-28T19:55:57.863 回答