加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

postgresql – 表分区与非分区表,包含许多索引

发布时间:2020-12-13 18:06:40 所属栏目:百科 来源:网络整理
导读:我有一个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) 这是我创建和插
我有一个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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读