postgresql – 表分区与非分区表,包含许多索引
我有一个DB“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; 这是我的TRIGGER: 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行之后,我试图比较这两个DB之间的数据查看速度.我用来比较的查询: select * from ctm_test."t_d_gate_out" where d_gate_out BETWEEN '2013-10-01' AND '2013-10-31' 我尝试多次执行该查询后的结果,执行时间几乎相同.因此,分区表无法更快地查看数据.
只要每个查询都可以使用索引,它们的执行几乎相同. (实际上,您应该在分区表上看到顺序扫描,因为您从中读取了所有行.)
通过索引访问很快(我希望位图索引扫描).单片表上的索引(更大)(并且还需要一个额外的前导列),这可能会挑战您的RAM大小,并且第一次运行将花费更多.但是只要索引驻留在RAM中并且你有足够的数量,你就不会注意到进一步的调用.在其他情况下,您可能从分区中获得更多利益. 或者更糟糕的是:涉及多个分区的查询往往比单个大表上的等效查询慢.访问单个表会更便宜.通常情况下,不是像您所示的查询的情况:在较小的时间范围内,仅跨越一个(或几个)分区.最糟糕的情况是查询从整个范围读取行,随机展开. 如果您的表很大并且查询主要位于几个分区上,您可能会开始看到一个好处.小分区的索引要小得多,而且更容易适应RAM(并保留在那里).大量的RAM是性能的关键因素(除了匹配索引). 索引的数量几乎完全与读取性能无关.一般准则是尽可能少地创建索引,但需要尽可能多的索引.如果有疑问,支持简单的索引,这些索引可以针对高度专业化的索引提供更多种类的查询,针对单个用例量身定制(除非这种情况特别重要).任何未使用的索引只是写入性能的负担而浪费空间. 如果您最关心的是阅读性能,那么单个大桌上的partial indexes可能是另一种选择. 除此之外:您的触发功能可以在多个地方得到改善.从更易读的格式开始,这个提示: > PL/pgSQL checking if a row exists – SELECT INTO boolean 带触发功能的相关答案: > Self-managing PostgreSQL partition tables (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |