真空分析模式postgres中的所有表

时间:2015-04-17 22:43:13

标签: postgresql

我有一个非常大的postgres数据库,其中有一个特定的模式,它被放入并在每晚重新创建。在创建该模式中的所有表之后,我想对它们进行真空分析,但是数据库是如此之大,以至于如果执行完整的数据库VACUUM ANALYZE;则需要大约半小时。

如何在不为每个表编写单独的SQL命令的情况下,真正分析此模式中的每个表?

6 个答案:

答案 0 :(得分:9)

下面的bash函数利用psql真空分析模式中由变量$PGSCHEMA

标识的表

完全披露:我在发布问题之前制定了这个答案,但认为这对其他人有用,并且很想看到任何其他解决方案。

PGUSER=your_postgres_username
PGHOST=your_postgres_host
PGDBNAME=your_postgres_db_name
PGSCHEMA=your_postgres_schema    

vacuum_analyze_schema() {
    #  vacuum analyze only the tables in the schema named in the variable $PGSCHEMA

    psql_tbls="\dt $PGSCHEMA.*"
    sed_str="s/$PGSCHEMA\s+\|\s+(\w+)\s+\|.*/\1/p"

    # extract schema table names from psql output and put them in a bash array
    echo "$psql_tbls | psql -d $PGDBNAME -U $PGUSER -h $PGHOST | sed -nr '$sed_str'"
    table_names=$(echo "$psql_tbls" | psql -d $PGDBNAME -U $PGUSER -h $PGHOST  | sed -nr "$sed_str")
    tables_array=($(echo $table_names | tr '\n' ' '))

    # loop through the table names creating and executing a vacuum command for each one
    for t in "${tables_array[@]}"; do
        q="VACUUM ANALYZE $PGSCHEMA.$t;"
        echo "psql -d $PGDBNAME -U $PGUSER -h $PGHOST -c $q"
        psql -d $PGDBNAME -U $PGUSER -h $PGHOST -c "$q"
    done
}

vacuum_analyze_schema;

答案 1 :(得分:3)

您可以使用以下pl / pgsql脚本(如果您只想分析,无法从函数或多命令字符串执行vacuum):

DO $$
DECLARE
  tab RECORD;
  schemaName VARCHAR := 'your_schema';
BEGIN
  for tab in (select t.relname::varchar AS table_name
                FROM pg_class t
                JOIN pg_namespace n ON n.oid = t.relnamespace
                WHERE t.relkind = 'r' and n.nspname::varchar = schemaName
                order by 1)
  LOOP
    RAISE NOTICE 'ANALYZE %1.%2', schemaName, tab.table_name;
    EXECUTE 'ANALYZE '||schemaName||'.'||tab.table_name;
  end loop;
end
$$;

答案 2 :(得分:1)

一种基于@Grant Humphries和@Fritz的解决方案,但更短,更简单:

PGUSER=your_postgres_username
PGHOST=your_postgres_host
PGPORT=your_postgres_port
PGDB=your_postgres_db_name
PGSCHEMA=your_postgres_schema  

for table in $(psql -h ${PGHOST} -p ${PGPORT} -d ${PGDB} -U ${PGUSER} \
  -c "select tablename from pg_tables where schemaname = '${PGSCHEMA}';" | \
  tail -n +3 | head -n -2); do
    psql -h ${PGHOST} -p ${PGPORT} -d ${PGDB} -U ${PGUSER} \
         -c "VACUUM (ANALYZE) ${PGSCHEMA}.${table};";
done

与上述解决方案的区别:

  • 通过直接查询系统目录视图pg_tables来获取表名。这使得提取表名更加容易,因为我们只需要使用head和tail删除输出中的页眉和页脚即可。
  • 为需要安装的那些端口添加了端口号。
  • 使用括号将vacuum语句更新为当前(PostgreSQL 9.0及更高版本)语法。根据{{​​3}}:“不带括号的语法已弃用。”

答案 3 :(得分:0)

do
$$
declare
  r record;
  schemaname varchar := 'contact';
begin
    perform dblink_connect('vacuum_connection', 'dbname=' || current_database());
    for r in (  select t.oid::regclass::text tname
                from pg_class t
                where t.relkind = 'r' and t.relnamespace = schemaname::regnamespace)
    loop
        raise notice '%1', r.tname;
        perform dblink_exec('vacuum_connection', 'vacuum analyze ' || r.tname);
    end loop;
    perform dblink_disconnect('vacuum_connection');
end
$$

答案 4 :(得分:0)

难道不是很简单吗?

psql -t -A -U postgres -c "select format('analyse verbose %I.%I;', n.nspname::varchar, t.relname::varchar) FROM pg_class t JOIN pg_namespace n ON n.oid = t.relnamespace WHERE t.relkind = 'r' and n.nspname::varchar = 'your_schema' order by 1" | psql -U postgres

选项-t仅打印行(不包含标题),而-A避免格式化

答案 5 :(得分:0)

在寻找这个确切问题的答案时,我发现PPH给出的解决方案是更可取的。不幸的是,给定的命令行开箱即用(在Postgres服务器v9.6.13上使用psql 10.8进行了测试)。 这是我成功用于VACUUM ANALYZE特定PostgreSQL数据库中特定模式的所有表的命令行:

psql -t -A -d "YOUR_DATABASE" -c "select format('vacuum analyse verbose %I.%I;', n.nspname::varchar, t.relname::varchar) FROM pg_class t JOIN pg_namespace n ON n.oid = t.relnamespace WHERE t.relkind = 'r' and n.nspname::varchar = 'YOUR_SCHEMA' order by 1" | psql -U postgres -d "YOUR_DATABASE"

您必须将三个大写字母替换为适用于您的案例的值。为我完美地工作。