我有一个数据库“DB_One”,其中有一个名为
t_d_gate_out
的主表,上面有 8 个索引。我创建了另一个带有分区 t_d_gate_out
的数据库(我们称之为“DB_Two”)。它按月和年分区(子表示例:t_d_gate_out09-2013
),它有两个索引(d_gate_out
和每个子表的新列:i_trx_own
)
这是我创建和插入子表的功能:
CREATE OR REPLACE FUNCTION ctm_test.gateout_partition_function()
RETURNS trigger AS
$BODY$
DECLARE new_time text;
tablename text;
seqname text;
seqname_schema text;
bulantahun text;
bulan text;
bulan2 text;
tahun text;
enddate text;
result record;
BEGIN new_time := to_char(NEW.d_gate_out,'MM-YYYY');
bulan:=to_char(NEW.d_gate_out,'MM');
bulan2:=extract(month from NEW.d_gate_out);
tahun:=to_char(NEW.d_gate_out,'YYYY');
bulantahun := new_time;
tablename := 't_d_gate_out'||bulantahun;
seqname := 't_d_gate_out'||bulantahun||'_seq';
seqname_schema := 'ctm_test.t_d_gate_out'||bulantahun||'_seq';
PERFORM 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE
c.relkind = 'r' AND c.relname = tablename AND n.nspname = 'ctm_test';
IF NOT FOUND THEN EXECUTE 'CREATE TABLE ctm_test.' || quote_ident(tablename) || ' ( i_trx_own
serial PRIMARY KEY, CHECK (extract(month from d_gate_out)=' || bulan2 || ' AND extract(year from
d_gate_out)=' || tahun || ')) INHERITS (ctm_test.t_d_gate_out)';
EXECUTE 'ALTER TABLE ctm_test.' || quote_ident(tablename) || ' OWNER TO postgres'; EXECUTE 'GRANT
ALL ON TABLE ctm_test.' || quote_ident(tablename) || ' TO postgres';
EXECUTE 'CREATE INDEX ' || quote_ident(tablename||'_indx1') || ' ON ctm_test.' || quote_ident
(tablename) || ' (i_trx_own);CREATE INDEX ' || quote_ident(tablename||'_indx2') || ' ON ctm_test.' || quote_ident
(tablename) || ' (d_gate_out)'; END IF;
EXECUTE 'INSERT INTO ctm_test.' || quote_ident(tablename) || ' VALUES ($1.*)' USING NEW; RETURN
NULL; END; $BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION ctm_test.gateout_partition_function()
OWNER TO postgres;
这是我的触发点:
CREATE TRIGGER gateout_master_trigger
BEFORE INSERT
ON ctm_test.t_d_gate_out
FOR EACH ROW
EXECUTE PROCEDURE ctm_test.gateout_partition_function();
插入大约 200k 行后,我试图比较这 2 个数据库之间查看数据的速度。我用来比较的查询:
select * from ctm_test."t_d_gate_out"
where d_gate_out BETWEEN '2013-10-01' AND '2013-10-31'
我多次尝试执行该查询后的结果,执行时间几乎相同。所以分区表并不能有效地更快地查看数据。
我的分区正确吗?
200K 行并不是很多。
当您的完整表大于 RAM 时,分区主要有帮助,但大多数查询都可以从单个部分表中提供服务。
只要您的每个查询都可以使用索引,它们的执行效果几乎相同。 (实际上,您应该看到分区表上的顺序扫描,因为您从中读取了所有行。)
通过索引访问速度很快(我希望位图索引扫描)。整体表上的索引更大(并且还需要额外的前导列),这可能会挑战您的 RAM 大小,并且第一次运行的成本会更高。但是,一旦索引驻留在 RAM 中并且您有足够的内存,您就不会注意到进一步的调用。在其他情况下,您可能会从分区中获益更多。
或更糟糕:涉及多个分区的查询往往比单个大表上的等效查询慢慢。访问单个表更便宜。对于像您演示的这样的查询,通常情况并非如此:在较小的时间范围内,仅跨越一个(或几个)分区。最坏的情况是从整个范围内随机分散读取行的查询。 如果您的表
巨大并且查询主要在几个分区上,您可能会开始看到好处。小分区的索引要小得多,并且更容易装入 RAM(并保留在那里)。 充足的 RAM 是性能的关键因素(除了匹配索引之外)。 索引数量与读取性能几乎完全
无关。一般准则是创建尽可能少的索引,但根据需要创建尽可能多的索引。如果有疑问,请优先选择可以服务更多类型查询的简单索引,而不是针对单个用例量身定制的高度专业化索引(除非该情况特别重要)。任何未使用的索引都只是写入性能的负担并浪费空间。 如果您最关心读取性能,单个大表上的部分索引
可能是一种替代方案。 旁白:你的触发功能可以在多个地方得到改进。从更易读的格式和这个提示开始:
PL/pgSQL 检查行是否存在 - SELECT INTO boolean
自我管理 PostgreSQL 分区表