需要脚本删除较大的索引,并在环境启动后使用postgresql中的备份重新创建这些索引

时间:2018-01-15 15:05:35

标签: indexing plpgsql psql postgresql-9.2

我正在寻找帮助,以尽量减少pg_basebackup实用程序所花费的时间。

我们正在使用pg_basbackup实用程序使用以下命令来备份数据库。

$PGHOME/bin/pg_basebackup -p 5433 -U postgres -P -v -x --format=tar --gzip --compress=6 --pgdata=- -D /opt/backup_db

pg_basebackup不依赖于任何postgresql配置参数。如果我选择gzip格式,我们需要按时妥协。

我们计划通过以下步骤进行备份,以最大限度地缩短数据库备份时间。如果我错了,请纠正我。

1)识别较大的索引(大小超过256MB)并删除这些索引。由于这个数据库的大小会减少。 2)备份数据库。使用此备份创建一个新环境。 3)在我们创建使用备份创建的环境的环境中重新创建索引。

注意: - 我们将使用备份创建新环境。在该环境中,由于我们的产品迁移,我们应用了几个ddls和dml并将其作为实时数据库。

我是postgres数据库的新手。你能帮我构建一个删除和创建索引的查询吗?

1 个答案:

答案 0 :(得分:1)

必要的信息在视图中pg_indexes

我写了一些脚本,可用于索引维护。小索引通常可以直接重新编制索引。有一个写锁定,但它不需要太多时间。如果无法锁定,则无法使用此脚本:

psql -At -c "select 'REINDEX INDEX' || c.relname from pg_class c where relkind = 'i' and pg_table_size(c.oid) < 1024*1024*1024;" mydb | psql -S mydb

查询:

SELECT c.relname
   FROM pg_class
  WHERE relkind = 'i'
    AND pg_table_size(c.oid) < 1024*1024*1024;

选择小于1GB的索引。在脚本中,我为这些索引创建了REINDEX INDEX命令。

通过更大的指数通常会更多的工作。由于锁定时间过长,因此无法REINDEX INDEXCREATE INDEX CONCURRENTLY命令是解决方案。但是对于约束指数来说,还有更多的魔力。它可以原子地做:

alter table T1
  drop constraint T1_pkey,
  add constraint T1_pkey PRIMARY KEY USING INDEX T1_xx_pk2; 

几年前我编写了脚本,它在选定的表上进行并发重建索引:

create table commands(cmd text);

do $$
declare 
  r record;
  newname text;
begin
  for r in 
    SELECT c2.relname as indexname, i.indisprimary,
           pg_catalog.pg_get_indexdef(i.indexrelid, 0, true) as indexdef,
           pg_catalog.pg_get_constraintdef(con.oid, true),
           c.oid::regclass as tablename
      FROM pg_catalog.pg_class c,
           pg_catalog.pg_class c2, pg_catalog.pg_index i
           LEFT JOIN pg_catalog.pg_constraint con 
                     ON (conrelid = i.indrelid 
                       AND conindid = i.indexrelid
                       AND contype IN ('p','u','x'))
     WHERE c.oid = 'mytable'::regclass
       AND c.oid = i.indrelid AND i.indexrelid = c2.oid
  loop
    newname = 'fresh_' || md5(r.indexname || r.tablename);
    -- inject CONCURRENTLY keyword
    insert into commands
      values(replace(replace(r.indexdef, 'INDEX', 'INDEX CONCURRENTLY'), r.indexname, newname) || ';');
    if r.indisprimary then
      insert into commands
        values(format('ALTER TABLE %I DROP CONSTRAINT %I, ADD CONSTRAINT %I PRIMARY KEY USING INDEX %I;',
            r.tablename, r.indexname, r.indexname, newname));
    else
      insert into commands
        values(format('BEGIN;DROP INDEX %I;', r.indexname) || format('ALTER INDEX %I RENAME TO %I; COMMIT;', newname, r.indexname));
    end if;
    raise notice 'refreshed index: %', r.indexname;
  end loop;
end;
$$ language plpgsql;

所有必要的命令都存储在表commands

只是几个笔记:

  1. 通常你应该非常小心地删除索引 - 某些应用程序可以停止工作

  2. 当256MB的索引出现问题(非常小的索引)时,可能您可以使用pg_dump进行备份。 pg_dump仅备份索引定义。它不会备份索引内容 - 也许它更适合您pg_basebackup

  3. 的PostgreSQL-9.2。是不受支持的PostgreSQL版本。你应该做升级。