POSTGRESQL analyze table 到底做了什么与扩展统计

本文详细介绍了PostgreSQL中ANALYZE命令的作用,如何收集表状态以提升查询效率,包括自动分析、列选择和pg_statistic系统。重点讲解了统计信息的收集、直方图分析及如何针对特定场景创建扩展统计信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PostgreSQL  中对表的状态是有单独的命令来进行状态的收集的,到底怎么对表来进行状态的收集,并且都做了什么,我们怎么来依靠这些信息来对查询进行有益的帮助。这些都将在这篇文章里面探讨。

首先我们对PG12 中,关于Analyze 的注释来仔细的阅读一遍

ANALYZE collects statistics about the contents of tables in the database, and stores the results in the pg_statistic system catalog. Subsequently, the query planner uses these statistics to help determine the most efficient execution plans for queries.

Without a table_and_columns list, ANALYZE processes every table and materialized view in the current database that the current user has permission to analyze. With a list, ANALYZE processes only those table(s). It is further possible to give a list of column names for a table, in which case only the statistics for those columns are collected.

分析收集数据库中表中关于内容的状态,并将结果存储到pg_statistic 系统目录中,随后查询执行计划的工作中会利用这些数据来帮助查询更有效率的执行,节省查询时间。Analyze命令对于当前数据库中的每一个表或者物化视图进行分析, 前提是操作的用户必须具有这些表的权限,或者是这个数据库的OWNER,或SUPERUSER. 进一步讲,对于表中的某些列进行状态信息的收集.

并且对于表的分析,中外部的表也是被支持的,但也要看你的外部的表是否支持analyzed命令,部分不支持analyze的外部数据的封装器. 在postgresql 默认的设置中, autovacuum 进程,会自动去分析表,当然您也可以根据ORACLE的经验,来对表定期的进行analyze 命令的执行,来收集表中的数据变化后的状态, 这对于加速查询是十分有帮助的.  可以在比较低的工作时间中去运行analyze来保证统计信息的更新性.

这里需要提及的analyze 需要一个读锁来,此时这个工作可以和其他的工作并行工作。这里的工作包含统计表中大部分的列的值的分布,并且可以通过直方图展示每列值的分布的情况。

对于大表,analyze 会对大表取一个随机的表的内容,而不会傻到对每一个行进行一个扫描.这样做的好处是节省数据判断的时间. 但这样的结果是很可能每次运行ANALYZE会有不同的结果,当然一般这样的变化是细微的. 这样的情况下我们可以提高analyze 的手动的次数,提高整体查询计划的平稳性.

而这些数据到底存到了哪里, pg_statistic, pg_statistic 是存储analyze 命令执行后或者autovacuum 执行后统计的内容存储到了这个表.  这里注意存储的数据的值基本都是近似值. 

starelid:  starelid 是pg_statistic中关于这条记录是表的oid信息

staattnum:  所属表的列的编号

stainherit :  这个列标明这个列是否包含继承的子列,并且是否被统计,TRUE为统计

stanumber1:是我们这列存储的值的分布情况

stavalues1:   存储列中存储的值的明细

select * from pg_stats;     pg_stats 是一个类似于可以提供相关数据库方便人类阅读的VIEW ,实际的数据还是通过pg_statistic 获得的。

对数据库表的状态的收集,一般通过autovacuum来就可以了,对于一些比较重要的业务大表,我们也可以学习类似ORACLE 定期对数据进行统计数据分析的方法来进行。

尤其我们还可以针对特定的字段来进行数据的分析和数据的收集,类似我们有一个比较大的表,并且列比较多拿此时我们对于这个表的某个字段查询时频繁,并且是复杂的,同时这个表的这个列的值还是经常变化的。那么此时我们可以针对这个表的这个列来进行分析。

SELECT relname, relkind, reltuples, relpages
FROM pg_class order by reltuples desc;


我们可以看到这个表的数据的行数比较大,并且值的分布也比较广泛,也就说明、并且这个字段是bid ,有此我们可以得到两个信息

1  我们如果对这个表的统计信息进行收集,通过普通的方式来收集统计信息,是通过评估的方式,而不会是完全的方式。 

2  我们分析可以对单独的这个bid 字段进行分析

以上是建立在我们的查询的where 条件是带有bid 这个条件的, 反过来我们很多的查询并不是单列查询,查询的条件和语句都比较复杂,例如 group by,

这样的情况下我们需要的统计信息可能就需要更有关系性,也就是GROUP BY 中的字段的之间的关系,通过一个统计信息能进行展示。

那我们可以做什么以下以 pgbench_accounts 中有两个字段  bid和 abalance 那么我们需要对这个表经常的使用group by 语句 ,那我们可以通过以下的方式来给查询提供更有效的查询的统计信息。

create  statistics bid_ab (ndistinct) on bid,abalance from pgbench_accounts;

analyze pgbench_accounts;

SELECT stxkeys AS k, stxdndistinct AS nd
test-#   FROM pg_statistic_ext join pg_statistic_ext_data on (oid = stxoid)
test-#   WHERE stxname = 'bid_ab';

以上我们其实就建立了一个扩展的统计信息,来帮助某些特殊的查询得到更加准确的统计分析信息。

<think>好的,用户的问题是关于如何通过SQL查询表结构(table schema)来获取每个列的统计数据。首先,我需要确定用户的具体需求是什么。他们可能想了解数据库中各个表的列信息,比如列名、数据类型、是否允许空值等,或者更详细的统计信息,比如每个列的最大值、最小值、平均值等。 接下来,我需要回忆相关的SQL知识。在MySQL中,`INFORMATION_SCHEMA.COLUMNS` 表存储了所有列的信息,包括列名、数据类型、是否可为空等。用户提到的引用[2]中也提到了这个表,可以用来查找包含特定列名的表。因此,首先应该考虑使用这个系统视图来获取基本的表结构信息。 然后,用户提到“统计数据”,这可能涉及到性能统计信息。引用[1]提到统计数据存放在`performance_schema`中的`objects_summary_global_by_type`表。不过,这个表可能存储的是对象级别的统计信息,比如表的访问次数,而不是具体列的统计数据。因此,可能需要结合不同的系统表来获取更详细的信息。 对于列的详细统计信息,比如最大值、最小值、平均值等,这些通常是通过`ANALYZE TABLE`命令生成的,存储在MySQL的统计表中。不过,这些信息可能不在`INFORMATION_SCHEMA`中,而是在`mysql`库的某些表中,或者通过`SHOW COLUMN_STATISTICS`来查看。不过需要注意的是,不同数据库系统(如MySQL、SQL Server、PostgreSQL)可能有不同的实现方式,用户没有明确说明使用的是哪种数据库,这里假设是MySQL。 用户提供的引用[4]是关于创建索引的语句,可能当前问题关联不大,但索引信息也可能存储在`INFORMATION_SCHEMA.STATISTICS`表中,可以用来查看索引相关的统计信息。 现在需要整合这些信息,给出一个综合的查询方法。首先,获取表结构的基本信息,可以使用`INFORMATION_SCHEMA.COLUMNS`。然后,如果需要更详细的统计信息,可能需要查询`performance_schema`或其他系统表,或者使用`SHOW`语句。此外,用户可能还需要使用`ANALYZE TABLE`来生成最新的统计信息。 考虑到用户可能没有执行过`ANALYZE TABLE`,统计信息可能不存在或过时,因此需要提醒他们先运行该命令。另外,需要注意权限问题,访问`INFORMATION_SCHEMA`和`performance_schema`可能需要特定权限。 最后,根据用户提供的引用[2]中的示例,可以构造一个基本的查询,然后扩展它以包含统计信息。可能需要使用`LEFT JOIN`来结合不同的系统表,或者使用子查询。如果某些统计信息无法直接通过SQL查询获取,可能需要使用存储过程或自定义函数,但这可能超出用户当前的需求范围。 总结步骤: 1. 使用`INFORMATION_SCHEMA.COLUMNS`获取表结构的基本信息。 2. 结合`performance_schema`或其他统计表获取列的统计信息。 3. 可能需要先执行`ANALYZE TABLE`来更新统计信息。 4. 处理不同数据库系统的差异,但假设用户使用MySQL。 5. 注意权限和系统表的可用性。 可能的问题:如何区分不同数据库系统的实现?如果用户使用的是SQL Server或其他系统,答案会不同,但根据引用中的示例,用户可能在使用MySQL,所以优先考虑MySQL的解决方案。</think>在MySQL中获取表结构及列统计数据的完整解决方案如下: 1. 基础表结构查询(含列基础信息): ```sql SELECT TABLE_SCHEMA AS '数据库', TABLE_NAME AS '表名', COLUMN_NAME AS '列名', COLUMN_TYPE AS '数据类型', IS_NULLABLE AS '允许空值', COLUMN_DEFAULT AS '默认值', COLUMN_COMMENT AS '列注释' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'your_database_name' AND TABLE_NAME = 'your_table_name'; ``` 2. 扩展统计信息查询(需先执行`ANALYZE TABLE`): ```sql ANALYZE TABLE your_database_name.your_table_name; SELECT COLUMN_NAME AS '列名', HISTOGRAM->>'$.number-of-buckets-specified' AS '直方图桶数', CAST(HISTOGRAM->>'$.data-type' AS CHAR) AS '数据类型', CAST(HISTOGRAM->>'$.last-updated' AS DATETIME) AS '最后统计时间' FROM INFORMATION_SCHEMA.COLUMN_STATISTICS WHERE SCHEMA_NAME = 'your_database_name' AND TABLE_NAME = 'your_table_name'; ``` 3. 性能统计信息查询(需要开启performance_schema)[^1]: ```sql SELECT OBJECT_SCHEMA AS '数据库', OBJECT_NAME AS '表名', COUNT_STAR AS '总操作次数', SUM_TIMER_WAIT/1000000000 AS '总耗时(秒)' FROM performance_schema.objects_summary_global_by_type WHERE OBJECT_TYPE = 'TABLE' AND OBJECT_SCHEMA = 'your_database_name'; ``` 4. 索引统计信息查询[^4]: ```sql SELECT INDEX_NAME AS '索引名称', COLUMN_NAME AS '列名', SEQ_IN_INDEX AS '索引顺序', CARDINALITY AS '唯一值数量' FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = 'your_database_name' AND TABLE_NAME = 'your_table_name'; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值