#### 13.7.3.1 ANALYZE TABLE 语句

[](<>)

```
ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
    TABLE tbl_name [, tbl_name] ...

ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
    TABLE tbl_name
    UPDATE HISTOGRAM ON col_name [, col_name] ...
        [WITH N BUCKETS]

ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
    TABLE tbl_name
    DROP HISTOGRAM ON col_name [, col_name] ...
```

[`分析表`](analyze-table.html)生成表统计信息：

-   [`分析表`](analyze-table.html)没有任何一个`直方图`子句执行键分布分析并存储命名表的分布。为了`MyISAM`表，[`分析表`](analyze-table.html)对于密钥分布分析等价于使用[**myisamchk——分析**](myisamchk.html).

-   [`分析表`](analyze-table.html)与`更新直方图`子句为命名的表列生成直方图统计信息并将它们存储在数据字典中。此语法只允许使用一个表名。

-   [`分析表`](analyze-table.html)与`删除直方图`子句从数据字典中删除命名表列的直方图统计信息。此语法只允许使用一个表名。

    该声明要求[`选择`](privileges-provided.html#priv_select)和[`插入`](privileges-provided.html#priv_insert)表的特权。

[`分析表`](analyze-table.html)与`InnoDB`,`新开发银行`， 和`MyISAM`表。它不适用于视图。

如果[`innodb_read_only`](innodb-parameters.html#sysvar_innodb_read_only)系统变量已启用，[`分析表`](analyze-table.html)可能会失败，因为它无法更新数据字典中的统计表，这些表使用`InnoDB`.为了[`分析表`](analyze-table.html)更新密钥分布的操作，即使该操作更新了表本身（例如，如果它是`MyISAM`桌子）。要获取更新的分布统计信息，请设置[`information_schema_stats_expiry=0`](server-system-variables.html#sysvar_information_schema_stats_expiry).

[`分析表`](analyze-table.html)支持分区表，您可以使用`ALTER TABLE ...分析分区`分析一个或多个分区；有关详细信息，请参阅[第 13.1.9 节，“ALTER TABLE 语句”](alter-table.html)， 和[第 24.3.4 节，“分区维护”](partitioning-maintenance.html).

在分析过程中，表被一个读锁锁定`InnoDB`和`MyISAM`.

[`分析表`](analyze-table.html)从表定义缓存中删除表，这需要刷新锁。如果有长时间运行的语句或事务仍在使用该表，则后续语句和事务必须等待这些操作完成，然后释放刷新锁。因为[`分析表`](analyze-table.html)本身通常很快完成，延迟事务或涉及同一张表的语句可能不是由于剩余的刷新锁造成的。

默认情况下，服务器写入[`分析表`](analyze-table.html)对二进制日志的语句，以便它们复制到副本。要禁止记录，请指定可选的`NO_WRITE_TO_BINLOG`关键字或其别名`当地的`.

-   [分析表输出](analyze-table.html#analyze-table-output)

-   [密钥分布分析](analyze-table.html#analyze-table-key-distribution-analysis)

-   [直方图统计分析](analyze-table.html#analyze-table-histogram-statistics-analysis)

-   [其他注意事项](analyze-table.html#analyze-table-other-considerations)

##### 分析表输出

[`分析表`](analyze-table.html)返回具有下表所示列的结果集。

| 柱子 | 价值 |
| --- | --- |
| `桌子` | 表名 |
| `操作` | `分析`要么`直方图` |
| `消息类型` | `状态`,`错误`,`信息`,`笔记`， 要么`警告` |
| `消息文本` | 信息性消息 |

##### 密钥分布分析

[`分析表`](analyze-table.html)没有任何一个`直方图`子句执行键分布分析并存储一个或多个表的分布。任何现有的直方图统计信息均不受影响。

如果自上次键分布分析后表未更改，则不会再次分析该表。

MySQL 使用存储的键分布来决定表的连接顺序，以便在非常量上进行连接。此外，在决定将哪些索引用于查询中的特定表时，可以使用键分布。

要检查存储的密钥分布基数，请使用[`显示索引`](show-index.html)声明或`INFORMATION_SCHEMA` [`统计数据`](information-schema-statistics-table.html)桌子。看[第 13.7.7.22 节，“显示索引语句”](show-index.html)， 和[第 26.3.34 节，“信息\_SCHEMA 统计表”](information-schema-statistics-table.html).

为了`InnoDB`表，[`分析表`](analyze-table.html)通过在每个索引树上执行随机潜水并相应地更新索引基数估计来确定索引基数。因为这些只是估计，重复运行[`分析表`](analyze-table.html)可以产生不同的数字。这使得[`分析表`](analyze-table.html)快开`InnoDB`表但不是 100% 准确，因为它没有考虑所有行。

你可以使[统计数据](glossary.html#glos_statistics)收集者[`分析表`](analyze-table.html)通过启用更精确和更稳定[`innodb_stats_persistent`](innodb-parameters.html#sysvar_innodb_stats_persistent)，如中所述[第 15.8.10.1 节，“配置持久优化器统计参数”](innodb-persistent-stats.html).什么时候[`innodb_stats_persistent`](innodb-parameters.html#sysvar_innodb_stats_persistent)已启用，运行很重要[`分析表`](analyze-table.html)在对索引列数据进行重大更改后，因为不会定期重新计算统计信息（例如在服务器重新启动后）。

如果[`innodb_stats_persistent`](innodb-parameters.html#sysvar_innodb_stats_persistent)启用后，您可以通过修改[`innodb_stats_persistent_sample_pages`](innodb-parameters.html#sysvar_innodb_stats_persistent_sample_pages)系统变量。如果[`innodb_stats_persistent`](innodb-parameters.html#sysvar_innodb_stats_persistent)已禁用，修改[`innodb_stats_transient_sample_pages`](innodb-parameters.html#sysvar_innodb_stats_transient_sample_pages)反而。

有关密钥分布分析的更多信息，请参见`InnoDB`， 看[第 15.8.10.1 节，“配置持久优化器统计参数”](innodb-persistent-stats.html)， 和[第 15.8.10.3 节，“估计 InnoDB 表的分析表复杂性”](innodb-analyze-table-complexity.html).

MySQL 在连接优化中使用索引基数估计。如果连接没有以正确的方式优化，请尝试运行[`分析表`](analyze-table.html).在少数情况下[`分析表`](analyze-table.html)不会为您的特定表产生足够好的值，您可以使用`力指数`使用您的查询强制使用特定索引，或设置[`max_seeks_for_key`](server-system-variables.html#sysvar_max_seeks_for_key)系统变量以确保 MySQL 更喜欢索引查找而不是表扫描。看[第 B.3.5 节，“优化器相关问题”](optimizer-issues.html).

##### 直方图统计分析

[`分析表`](analyze-table.html)与`直方图`子句允许管理表列值的直方图统计信息。有关直方图统计信息，请参阅[第 8.9.6 节，“优化器统计”](optimizer-statistics.html).

可以使用以下直方图操作：

-   [`分析表`](analyze-table.html)带着`更新直方图`子句为命名的表列生成直方图统计信息，并将其存储在数据字典中。此语法只允许使用一个表名。

    可选的`与*`N`*水桶`子句指定直方图的存储桶数。价值*`N`*必须是1到1024之间的整数。如果省略该条款，则桶的数量为100。

-   [`分析表`](analyze-table.html)用一个`下降直方图`子句从数据字典中删除命名表列的直方图统计信息。此语法只允许使用一个表名。

    存储的直方图管理语句只影响命名列。考虑这些陈述：


```
ANALYZE TABLE t UPDATE HISTOGRAM ON c1, c2, c3 WITH 10 BUCKETS;
ANALYZE TABLE t UPDATE HISTOGRAM ON c1, c3 WITH 10 BUCKETS;
ANALYZE TABLE t DROP HISTOGRAM ON c2;
```

第一条语句更新列的直方图`c1`,`c2`和`c3`，替换这些列的任何现有直方图。第二条语句更新了`c1`和`c3`，离开`c2`直方图未受影响。第三条语句删除了`c2`把这些留给`c1`和`c3`不受影响的

加密表不支持直方图生成（以避免在统计数据中暴露数据）或`短暂的`桌子。

直方图生成适用于除几何图形类型（空间数据）和[`JSON`](json.html).

可以为存储列和虚拟生成列生成直方图。

无法为单列唯一索引覆盖的列生成直方图。

直方图管理语句尝试执行尽可能多的请求操作，并报告其余操作的诊断消息。例如，如果`更新直方图`语句为多个列命名，但其中一些列不存在或具有不受支持的数据类型，为其他列生成直方图，并为无效列生成消息。

直方图受以下DDL语句的影响：

-   [`升降台`](drop-table.html)删除删除表中列的直方图。

-   [`删除数据库`](drop-database.html)删除删除的数据库中任何表的直方图，因为该语句会删除数据库中的所有表。

-   [`重命名表`](rename-table.html)不删除直方图。相反，它会重命名直方图，使重命名后的表与新表名相关联。

-   [`改变桌子`](alter-table.html)删除或修改列的语句将删除该列的直方图。

-   [`改变桌子。。。转换为字符集`](alter-table.html)删除字符列的直方图，因为它们受字符集更改的影响。非字符列的直方图不受影响。

    这个[`直方图\u生成\u最大\u内存\u大小`](server-system-variables.html#sysvar_histogram_generation_max_mem_size)系统变量控制可用于生成直方图的最大内存量。全局值和会话值可以在运行时设置。

    改变全球经济[`直方图\u生成\u最大\u内存\u大小`](server-system-variables.html#sysvar_histogram_generation_max_mem_size)值需要足够的权限来设置全局系统变量。更改会话[`直方图\u生成\u最大\u内存\u大小`](server-system-variables.html#sysvar_histogram_generation_max_mem_size)值需要足够的权限来设置受限会话系统变量。看见[第5.1.9.1节，“系统变量权限”](system-variable-privileges.html).

    如果要读入内存以生成直方图的估计数据量超过[`直方图\u生成\u最大\u内存\u大小`](server-system-variables.html#sysvar_histogram_generation_max_mem_size)，MySQL对数据进行采样，而不是将其全部读入内存。采样均匀分布在整个表中。MySQL使用`系统`采样，这是一种页面级采样方法。

    这个`采样率`价值观`直方图`一栏[`信息模式。列_统计`](information-schema-column-statistics-table.html)可以查询表，以确定创建直方图所采样的数据的比例。这个`采样率`是一个介于0.0和1.0之间的数字。值为1表示读取了所有数据（无采样）。

    下面的示例演示了采样。确保数据量超过[`直方图\u生成\u最大\u内存\u大小`](server-system-variables.html#sysvar_histogram_generation_max_mem_size)限制出于本例的目的，在为数据生成直方图统计信息之前，将限制设置为较低的值（2000000字节）`出生日期`专栏`员工`桌子


```
mysql> SET histogram_generation_max_mem_size = 2000000;

mysql> USE employees;

mysql> ANALYZE TABLE employees UPDATE HISTOGRAM ON birth_date WITH 16 BUCKETS\G
*************************** 1. row ***************************
   Table: employees.employees
      Op: histogram
Msg_type: status
Msg_text: Histogram statistics created for column 'birth_date'.

mysql> SELECT HISTOGRAM->>'$."sampling-rate"'
       FROM INFORMATION_SCHEMA.COLUMN_STATISTICS
       WHERE TABLE_NAME = "employees"
       AND COLUMN_NAME = "birth_date";
+---------------------------------+
| HISTOGRAM->>'$."sampling-rate"' |
+---------------------------------+
| 0.0491431208869665              |
+---------------------------------+
```

A.`采样率`值0.0491431208869665意味着`出生日期`列被读入内存以生成直方图统计信息。

从MySQL 8.0.19开始`InnoDB`存储引擎为存储在中的数据提供自己的采样实现`InnoDB`桌子。当存储引擎不提供自己的数据时，MySQL使用的默认采样实现需要进行完整的表扫描，这对于大型表来说成本很高。这个`InnoDB`采样实现通过避免全表扫描来提高采样性能。

这个`样本页面`和`已跳过采样页面` [`INNODB_度量`](information-schema-innodb-metrics-table.html)计数器可用于监控数据的采样`InnoDB`数据页。（适用于一般情况）[`INNODB_度量`](information-schema-innodb-metrics-table.html)计数器使用信息，请参阅[第26.4.21节，“信息\_模式INNODB\_“指标表”](information-schema-innodb-metrics-table.html).)

下面的示例演示采样计数器的使用，这需要在生成直方图统计信息之前启用计数器。

```
mysql> SET GLOBAL innodb_monitor_enable = 'sampled%';

mysql> USE employees;

mysql> ANALYZE TABLE employees UPDATE HISTOGRAM ON birth_date WITH 16 BUCKETS\G
*************************** 1. row ***************************
   Table: employees.employees
      Op: histogram
Msg_type: status
Msg_text: Histogram statistics created for column 'birth_date'.

mysql> USE INFORMATION_SCHEMA;

mysql> SELECT NAME, COUNT FROM INNODB_METRICS WHERE NAME LIKE 'sampled%'\G
*************************** 1. row ***************************
 NAME: sampled_pages_read
COUNT: 43
*************************** 2. row ***************************
 NAME: sampled_pages_skipped
COUNT: 843
```

该公式根据采样计数器数据近似采样率：

```
sampling rate = sampled_page_read/(sampled_pages_read + sampled_pages_skipped)
```

基于采样计数器数据的采样率大致与`采样率`价值观`直方图`一栏[`信息模式。列_统计`](information-schema-column-statistics-table.html)桌子

有关为生成直方图而执行的内存分配的信息，请监视性能模式`内存/sql/直方图`仪器看见[第27.12.20.10节，“内存汇总表”](performance-schema-memory-summary-tables.html).

##### 其他考虑

`分析表`从列表中清除表统计信息[`信息模式。INNODB_表状态`](information-schema-innodb-tablestats-table.html)表和设置`STATS_已初始化`列到`未初始化`。下次访问该表时，将再次收集统计信息。
