我们有一个带有 Postgresql 9.1 数据库的电子商务门户。一张非常重要的表目前有 3200 万条记录。如果我们要交付所有项目,该表将增长到 3.2 亿条记录,主要是日期。这将是沉重的。
所以我们正在考虑水平分区/分片。我们可以将这张表中的项目水平分成 12 份(每月 1 份)。这样做的最佳步骤和技术是什么?数据库中的水平分区是否足够好,还是我们必须开始考虑分片?
我们有一个带有 Postgresql 9.1 数据库的电子商务门户。一张非常重要的表目前有 3200 万条记录。如果我们要交付所有项目,该表将增长到 3.2 亿条记录,主要是日期。这将是沉重的。
所以我们正在考虑水平分区/分片。我们可以将这张表中的项目水平分成 12 份(每月 1 份)。这样做的最佳步骤和技术是什么?数据库中的水平分区是否足够好,还是我们必须开始考虑分片?
虽然 3.2 亿并不小,但也不是很大。
这在很大程度上取决于您在表上运行的查询。如果您始终在查询中包含分区键,那么“常规”分区可能会起作用。
可以在 PostgreSQL wiki 中找到一个示例:
http ://wiki.postgresql.org/wiki/Month_based_partitioning
该手册还解释了分区的一些注意事项:
http ://www.postgresql.org/docs/current/interactive/ddl-partitioning.html
如果您正在考虑分片,您可能会阅读 Instagram(由 PostgreSQL 提供支持)是如何实现的:
http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram
如果您主要有读查询,另一种选择可能是使用流复制来设置多个服务器并通过连接到热备用进行读访问并连接到主服务器进行写访问来分发读查询。我认为pg-pool II可以自动(在某种程度上)做到这一点。这可以与分区相结合,以进一步减少查询运行时间。
如果您喜欢冒险并且没有非常迫切的需要这样做,您还可以考虑 Postgres-XC,它承诺支持透明的水平缩放: http:
//postgres-xc.sourceforge.net/
还没有最终版本,但看起来这不会花费太长时间
这是我的分区示例代码:t_master 是要在应用程序 t_1 中选择/插入/更新/删除的视图,t_2 是实际存储数据的基础表。
create or replace view t_master(id, col1)
as
select id, col1 from t_1
union all
select id, col1 from t_2
CREATE TABLE t_1
(
id bigint PRIMARY KEY,
col1 text
);
CREATE TABLE t_2
(
id bigint PRIMARY KEY,
col1 text
);
CREATE OR REPLACE FUNCTION t_insert_partition_function()
returns TRIGGER AS $$
begin
raise notice '%s', 'hello';
execute 'insert into t_'
|| ( mod(NEW.id, 2)+ 1 )
|| ' values ( $1, $2 )' USING NEW.id, NEW.col1 ;
RETURN NULL;
end;
$$
LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION t_update_partition_function()
returns TRIGGER AS $$
begin
raise notice '%s', 'hello';
execute 'update t_'
|| ( mod(NEW.id, 2)+ 1 )
|| ' set id = $1, col1 = $2 where id = $1'
USING NEW.id, NEW.col1 ;
RETURN NULL;
end;
$$
LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION t_delete_partition_function()
returns TRIGGER AS $$
begin
raise notice '%s', 'hello';
execute 'delete from t_'
|| ( mod(OLD.id, 2)+ 1 )
|| ' where id = $1'
USING OLD.id;
RETURN NULL;
end;
$$
LANGUAGE plpgsql;
CREATE TRIGGER t_insert_partition_trigger instead of INSERT
ON t_master FOR each row
execute procedure t_insert_partition_function();
CREATE TRIGGER t_update_partition_trigger instead of update
ON t_master FOR each row
execute procedure t_update_partition_function();
CREATE TRIGGER t_delete_partition_trigger instead of delete
ON t_master FOR each row
execute procedure t_delete_partition_function();
如果您不介意升级到 PostgreSQL 9.4,那么您可以使用pg_shard 扩展,它可以让您在多台机器上透明地对 PostgreSQL 表进行分片。每个分片都存储为另一个 PostgreSQL 服务器上的常规 PostgreSQL 表,并复制到其他服务器。它使用哈希分区来决定将哪些分片用于给定查询。如果您的查询具有自然分区维度(例如,客户 ID),那么 pg_shard 会很好地工作。