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

Gra*_*ies 10 postgresql

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

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

Gra*_*ies 9

下面的bash函数使用psql来真空分析由变量标识的模式中的表 psql

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

vacuum_analyze_schema() {
    # vacuum analyze only the tables in the specified schema

    # postgres info can be supplied by either passing it as parameters to this
    # function, setting environment variables or a combination of the two
    local pg_schema="${1:-${PG_SCHEMA}}"
    local pg_db="${2:-${PG_DB}}"
    local pg_user="${3:-${PG_USER}}"
    local pg_host="${4:-${PG_HOST}}"

    echo "Vacuuming schema \`${pg_schema}\`:"

    # extract schema table names from psql output and put them in a bash array
    local psql_tbls="\dt ${pg_schema}.*"
    local sed_str="s/${pg_schema}\s+\|\s+(\w+)\s+\|.*/\1/p"
    local table_names=$( echo "${psql_tbls}" | psql -d "${pg_db}" -U "${pg_user}" -h "${pg_host}"  | sed -nr "${sed_str}" )
    local 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
        echo "doing table \`${t}\`..."
        psql -d "${pg_db}" -U "${pg_user}" -h "${pg_host}" \
            -c "VACUUM (ANALYZE) ${pg_schema}.${t};"
    done
}
Run Code Online (Sandbox Code Playgroud)


小智 6

一个基于@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
Run Code Online (Sandbox Code Playgroud)

与上述解决方案的差异:

  • 通过直接查询系统目录视图pg_tables来获取表名。这使得提取表名称变得更容易,因为我们只需要使用 head 和 tail 删除输出中的页眉和页脚。
  • 添加端口号,用于需要的安装。
  • 将 Vacuum 语句更新为带括号的当前语法(PostgreSQL 9.0 及更高版本)。根据文档:“不推荐使用不带括号的语法。”


Fri*_*itz 5

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

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
$$;
Run Code Online (Sandbox Code Playgroud)

  • 使用 `format()` 对动态 SQL 正确处理可能需要引用的标识符更安全:`EXECUTE format('ANALYZE %I.%I', schemaName, tab.table_name);` (3认同)

小智 5

这样做不是更简单:

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
Run Code Online (Sandbox Code Playgroud)

选项 -t 仅打印行(无标题)和 -A 避免格式化