当前位置: 首页 > article >正文

PG vs MySQL 统计信息收集的异同

统计信息的作用

对于一条SQL,数据库选择何种方式执行,需要根据统计信息进行估算,计算出代价最低的执行计划。收集统计信息主要是为了让优化器做出正确的判断,选择最佳的执行计划。

PG的统计信息收集

PG的统计信息相关表

在PostgreSQL里面,统计信息存放于pg_statistics系统表中,由于pg_statistics里面的内容人为不易阅读,因此便有了pg_stats视图。

pg_class看pages和tuples

postgres=# select relname,relpages,reltuples::bigint from pg_class where relname='test'\gx
-[ RECORD 1 ]-----
relname   | test
relpages  | 443
reltuples | 100000

pg_stat_all_tables看活元组、死元组,上次统计信息收集时间

postgres=# select * from pg_stat_all_tables where relname='test'\gx
-[ RECORD 1 ]-------+------------------------------
relid               | 16388
schemaname          | public
relname             | test
seq_scan            | 0
last_seq_scan       | 
seq_tup_read        | 0
idx_scan            | 
last_idx_scan       | 
idx_tup_fetch       | 
n_tup_ins           | 100000
n_tup_upd           | 0
n_tup_del           | 0
n_tup_hot_upd       | 0
n_tup_newpage_upd   | 0
n_live_tup          | 100000
n_dead_tup          | 0
n_mod_since_analyze | 0
n_ins_since_vacuum  | 0
last_vacuum         | 
last_autovacuum     | 2025-01-21 10:46:51.330118+08
last_analyze        | 
last_autoanalyze    | 2025-01-21 10:46:51.353753+08
vacuum_count        | 0
autovacuum_count    | 1
analyze_count       | 0
autoanalyze_count   | 1

pg_stats看列的统计信息

\d pg_stats
                     View "pg_catalog.pg_stats"
         Column         |   Type   | Collation | Nullable | Default 
------------------------+----------+-----------+----------+---------
 schemaname             | name     |           |          | 
 tablename              | name     |           |          | 
 attname                | name     |           |          | 
 inherited              | boolean  |           |          | ---是否是继承列
 null_frac              | real     |           |          | ---null空值的比率
 avg_width              | integer  |           |          | ---平均宽度,字节
 n_distinct             | real     |           |          | ---大于零就是非重复值的数量,小于零则是非重复值的个数除以行数
 most_common_vals       | anyarray |           |          | ---高频值
 most_common_freqs      | real[]   |           |          | ---高频值的频率
 histogram_bounds       | anyarray |           |          | ---直方图
 correlation            | real     |           |          | ---物理顺序和逻辑顺序的关联性
 most_common_elems      | anyarray |           |          | ---高频元素,比如数组
 most_common_elem_freqs | real[]   |           |          |  ---高频元素的频率
 elem_count_histogram   | real[]   |           |          |  ---直方图(元素)

PG自动收集统计信息

• 触发vacuum analyze–>
• 表上新增(insert,update,delte) >= autovacuum_analyze_scale_factor* reltuples(表上记录数) + autovacuum_analyze_threshold

postgres=# show autovacuum_analyze_scale_factor;
 autovacuum_analyze_scale_factor 
---------------------------------
 0.1
(1 row)

postgres=# show autovacuum_analyze_threshold;
 autovacuum_analyze_threshold 
------------------------------
 50
(1 row)

PG手动收集统计信息

手动收集统计信息的命令是analyze命令,analyze的语法格式:

analyze [verbose] [table[(column[,…])]]

verbose:显示处理的进度,以及表的一些统计信息

table:要分析的表名,如果不指定,则对整个数据库中的所有表作分析 

column:要分析的特定字段的名字默认是分析所有字段

analyze 命令 会在表上加读锁,不影响表上其它SQL并发执行,对于大表只会读取表中部分数据。

MySQL的统计信息收集

MySQL的统计信息相关表

• 收集的表的统计信息存放在mysql数据库的innodb_table_stats表中。
• 索引的统计信息存放在mysql数据库的innodb_index_stats表中。

mysql>  select * from mysql.innodb_table_stats where table_name='actor';
+---------------+------------+---------------------+--------+----------------------+--------------------------+
| database_name | table_name | last_update         | n_rows | clustered_index_size | sum_of_other_index_sizes |
+---------------+------------+---------------------+--------+----------------------+--------------------------+
| sakila        | actor      | 2025-01-21 16:06:31 |    200 |                    1 |                        1 |
+---------------+------------+---------------------+--------+----------------------+--------------------------+
1 row in set (0.00 sec)

mysql>  select * from mysql.innodb_index_stats where table_name='actor'; 
+---------------+------------+---------------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name | index_name          | last_update         | stat_name    | stat_value | sample_size | stat_description                  |
+---------------+------------+---------------------+---------------------+--------------+------------+-------------+-----------------------------------+
| sakila        | actor      | PRIMARY             | 2025-01-21 16:06:31 | n_diff_pfx01 |        200 |           1 | actor_id                          |
| sakila        | actor      | PRIMARY             | 2025-01-21 16:06:31 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| sakila        | actor      | PRIMARY             | 2025-01-21 16:06:31 | size         |          1 |        NULL | Number of pages in the index      |
| sakila        | actor      | idx_actor_last_name | 2025-01-21 16:06:31 | n_diff_pfx01 |        121 |           1 | last_name                         |
| sakila        | actor      | idx_actor_last_name | 2025-01-21 16:06:31 | n_diff_pfx02 |        200 |           1 | last_name,actor_id                |
| sakila        | actor      | idx_actor_last_name | 2025-01-21 16:06:31 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| sakila        | actor      | idx_actor_last_name | 2025-01-21 16:06:31 | size         |          1 |        NULL | Number of pages in the index      |
+---------------+------------+---------------------+---------------------+--------------+------------+-------------+-----------------------------------+
7 rows in set (0.00 sec)

MySQL自动收集统计信息

• innodb_stats_persistent
是否把统计信息持久化。
对应表选项STATS_PERSISTENT

• innodb_stats_auto_recalc
当一个表的数据变化超过10%时是否自动收集统计信息,两次统计信息收集之间时间间隔不能少10秒。
对应的表选项STATS_AUTO_RECALC

• innodb_stats_on_metadata:其触发条件是表的元数据发生变化,如执行 ALTER TABLE 等操作修改表结构时,会触发统计信息的自动更新。

• innodb_stats_persistent_sample_pages
统计索引时的抽样页数,这个值设置得越大,收集的统计信息越准确,但收集时消耗的资源越大。
对应的表选项STATS_SAMPLE_PAGES

mysql> show variables like 'innodb_stat%';
+--------------------------------------+-------------+
| Variable_name                        | Value       |
+--------------------------------------+-------------+
| innodb_stats_auto_recalc             | ON          |
| innodb_stats_include_delete_marked   | OFF         |
| innodb_stats_method                  | nulls_equal |
| innodb_stats_on_metadata             | OFF         |
| innodb_stats_persistent              | ON          |
| innodb_stats_persistent_sample_pages | 20          |
| innodb_stats_transient_sample_pages  | 8           |
| innodb_status_output                 | OFF         |
| innodb_status_output_locks           | OFF         |
+--------------------------------------+-------------+
9 rows in set (0.00 sec)

对应的表选项可以这样设置
alter table actor stats_auto_recalc=0;

MySQL手动收集统计信息

analyze local table actor,rental;

analyze table 加MDL读锁,不影响DML的并行操作。

PG vs MySQL

在自动收集统计信息的方法上,PG比MySQL更加灵活,例如在表统计信息更新触发条件上, PG可以通过调整autovacuum_analyze_scale_factor的大小,来调整更新触发条件的数据量比例,而MySQL只能是10%,而且,因为PG还有autovacuum_analyze_threshold这个最小更新量保护机制,避免小表被频发触发统计信息收集影响性能。

在手动收集统计信息的方式上,PG和MySQL类似,都会加上读锁,MySQL加元数据读锁,不影响DML并行,PG加共享更新独占(SHARE UPDATE EXCLUSIVE),也不影响DML并行。

另外PG统计信息收集还有两个优势

统计信息的精度
MySQL统计信息的精度相对较低,尤其是在数据量较大且分布不均匀的情况下,可能无法准确地反映数据的实际情况,从而影响查询优化器的选择;而PG除了包含与 MySQL 类似的基本统计信息外,还提供了更丰富的统计内容,如多字段统计信息,可以对多个列的组合进行统计分析,为复杂的查询提供更精确的优化依据。

对性能的影响
MySQL自动收集统计信息可能会在一定程度上增加系统的负载,尤其是在数据量较大且修改频繁的情况下;而PostgreSQL的autovacuum 进程在后台自动运行,对系统性能的影响相对较小。但在进行大规模的数据操作或系统负载较高时,可能会导致一定的性能波动。


http://www.kler.cn/a/533311.html

相关文章:

  • visual studio安装
  • LeetCode 0922.按奇偶排序数组 II:O(1)空间复杂度-一次遍历双指针
  • 使用scikit-learn中的K均值包进行聚类分析
  • Maven jar 包下载失败问题处理
  • Kubernetes学习之包管理工具(Helm)
  • oracle:索引(B树索引,位图索引,分区索引,主键索引,唯一索引,联合索引/组合索引,函数索引)
  • Python 操作列表(元组)
  • C++ Primer 表达式基础
  • 用 Node.js 实现一个上传图片接口
  • modbus协议处理
  • 深度整理总结MySQL——Join的工作原理
  • 机器学习常用包numpy篇(四)函数运算
  • [创业之路-281]:在其位谋其职,企业不同角色,关心不同的问题。企业高层的书单、企业中层的书单、一线员工的书单
  • YK人工智能(六)——万字长文学会基于Torch模型网络可视化
  • Node.js:其实后端没那么难?
  • Spring AI 智能体通过 MCP 集成本地文件数据
  • 陷入闭包:理解 React 状态管理中的怪癖
  • JAVA:Spring Boot 集成 Disruptor 的技术指南
  • 深入理解指针(5)
  • 双系统共用一个蓝牙鼠标
  • 【Leetcode 每日一题 - 补卡】922. 按奇偶排序数组 II
  • OSCP - Other Machines - Blogger
  • 【华为OD机试python】日志采集系统【 E卷 | 2023 Q1 |100分】
  • RabbitMQ中的@Header
  • Maven 依赖管理基础
  • 网络命令