Postgres按字符前缀分区

时间:2016-06-07 21:19:54

标签: database postgresql partitioning

美好的一天,

我想检查在列前缀上对Postgres表进行分区的最佳方法是什么。我有一个大表(+ - 300 750万行×10列),我想将它分区为第1列的前缀。 数据如下:

ABCDEF1xxxxxxxx
ABCDEF1xxxxxxxy
ABCDEF1xxxxxxxz
ABCDEF2xxxxxxxx
ABCDEF2xxxxxxxy
ABCDEF2xxxxxxxz
ABCDEF3xxxxxxxx
ABCDEF3xxxxxxxz
ABCDEF4xxxxxxxx
ABCDEF4xxxxxxxy

他们只有10个分区,即ABCDEF0 ...-> ABCDEF9 ......

我目前所做的是制作如下表格:

CREATE TABLE public.mydata_ABCDEF1 (
CHECK ( col1 like 'ABCDEF1%' )
) INHERITS (public.mydata);

CREATE TABLE public.mydata_ABCDEF2 (
CHECK ( col1 like 'ABCDEF2%' )
) INHERITS (public.mydata);

等。然后触发器具有类似的逻辑:

IF ( NEW.col1 like 'ABCDEF1%' ) THEN 
    INSERT INTO public.mydata_ABCDEF1 VALUES (NEW.*);
ELSIF ( NEW.imsi like 'ABCDEF2%' ) THEN
    INSERT INTO public.simdata_ABCDEF2 VALUES (NEW.*);

我担心以这种方式进行分区会加快查询时间吗?或者我是否应该考虑对substr进行分区(不确定如何),或者我是否应该在该列上创建一个带有前缀和分区的新列?

任何建议都表示赞赏。

3 个答案:

答案 0 :(得分:2)

我知道这是一个老问题,但我正在添加这个答案以防其他人需要解决方案。

Postgres 10允许范围分区https://www.postgresql.org/docs/10/static/ddl-partitioning.html

虽然文档中的示例使用日期范围,但您也可以使用字符串范围,因为Postgres(大多数)使用ASCII排序。下面的代码创建一个父表,然后根据您的特定代码,两个子表应根据提供的前缀自动bin任何字母数字。范围必须是非重叠的,这就是为什么我根本无法创建从ABCDEF1到ABCDEF2的范围。

If Len(TextBox1) = "" And Len(TextBox2) > 0 Or Len(TextBox3) > 0 Then

答案 1 :(得分:0)

当每个分区表的索引被适当地分区时,它将显着加快查询速度,例如:

CREATE INDEX ON public.mydata_ABCDEF1 (...) WHERE col1 like 'ABCDEF1%';

答案 2 :(得分:0)

简短的回答是“可能不是”,但它实际上取决于您的查询究竟是什么。

问题是 - 你想用分区做什么?一般来说,PostgreSQL的btree索引非常快速有效地找到你要求的特定记录 - 比PostgreSQL更快地找出你存储数据的一组分区表中的哪个表。

分区非常有用的地方在于它有助于数据管理。它有用的原因是你可以经常根据时间进行分区,然后,当数据已经老化足够长时,只需删除旧的分区而不必发出“DELETE”查询,将记录标记为已删除,然后必须是VACUUM将空间回收,并最终导致表和索引膨胀。

300M记录是关于我可能考虑进行分区的那一点,但我不会跳到那时对数据进行分区而没有明确的理由为什么分区数据会有所帮助。

另外,请注意PostgreSQL的查询规划器不能很好地处理大量分区;成百上千的分区将减慢计划时间。对于9.5之前的版本,这不是很明显,但在9.5中,“EXPLAIN ANALYZE”将返回给定查询所需的计划时间:

=*> explain analyze select * from downloads;
                                                      QUERY PLAN                                       
-------------------------------------------------------------------------------------------------------
 Seq Scan on downloads  (cost=0.00..38591.76 rows=999976 width=193) (actual time=23.863..2088.732 rows=
 Planning time: 0.219 ms
 Execution time: 2552.878 ms
(3 rows)