### 8.9.6 优化器统计

[](<>)[](<>)

这`column_statistics`数据字典表存储有关列值的直方图统计信息，供优化器在构建查询执行计划时使用。要执行直方图管理，请使用[`分析表`](analyze-table.html)陈述。

这`column_statistics`表有以下特点：

-   该表包含除几何类型（空间数据）和[`JSON`](json.html).

-   该表是持久的，因此每次服务器启动时都不需要创建列统计信息。

-   服务器对表执行更新；用户没有。

    这`column_statistics`表不能被用户直接访问，因为它是数据字典的一部分。直方图信息可使用[`INFORMATION_SCHEMA.COLUMN_STATISTICS`](information-schema-column-statistics-table.html)，它被实现为数据字典表的视图。[`COLUMN_STATISTICS`](information-schema-column-statistics-table.html)有这些列：

-   `SCHEMA_NAME`,`TABLE_NAME`,`COLUMN_NAME`：应用统计信息的架构、表和列的名称。

-   `直方图`： 一种[`JSON`](json.html)描述列统计信息的值，存储为直方图。

    列直方图包含存储在列中的部分值范围的存储桶。直方图是[`JSON`](json.html)对象以允许灵活地表示列统计信息。这是一个示例直方图对象：


```
{
  "buckets": [
    [
      1,
      0.3333333333333333
    ],
    [
      2,
      0.6666666666666666
    ],
    [
      3,
      1
    ]
  ],
  "null-values": 0,
  "last-updated": "2017-03-24 13:32:40.000000",
  "sampling-rate": 1,
  "histogram-type": "singleton",
  "number-of-buckets-specified": 128,
  "data-type": "int",
  "collation-id": 8
}
```

直方图对象具有以下键：

-   `水桶`：直方图桶。桶结构取决于直方图类型。

    为了`单身人士`直方图，桶包含两个值：

    -   值 1：存储桶的值。类型取决于列数据类型。

    -   值 2：表示该值累积频率的双精度值。例如，0.25 和 0.75 表示列中 25% 和 75% 的值小于或等于存储桶值。

        为了`等高`直方图，桶包含四个值：

    -   值 1、2：存储桶的下限值和上限值。类型取决于列数据类型。

    -   值 3：表示该值的累积频率的双精度值。例如，0.25 和 0.75 表示列中 25% 和 75% 的值小于或等于存储桶上限值。

    -   值 4：从存储桶下限值到上限值的范围内不同值的数量。

-   `空值`: 一个介于 0.0 和 1.0 之间的数字，表示 SQL 列值的比例`空值`价值观。如果为 0，则该列不包含`空值`价值观。

-   `最近更新时间`: 生成直方图时，作为 UTC 值*`YYYY-MM-DD hh:mm:ss.uuuuuu`*格式。

-   `采样率`：一个介于 0.0 和 1.0 之间的数字，表示为创建直方图而采样的数据比例。值 1 表示读取了所有数据（无采样）。

-   `直方图类型`：直方图类型：

    -   `单身人士`：一个桶代表列中的一个值。当列中不同值的数量小于或等于在[`分析表`](analyze-table.html)生成直方图的语句。

    -   `等高`：一个桶代表一系列值。当列中不同值的数量大于在[`分析表`](analyze-table.html)生成直方图的语句。

-   `指定的桶数`: 指定的桶数[`分析表`](analyze-table.html)生成直方图的语句。

-   `数据类型`：此直方图包含的数据类型。当从持久存储读取直方图并将其解析到内存中时，这是需要的。该值是其中之一`整数`,`单位`（无符号整数），`双倍的`,`十进制`,`约会时间`， 要么`细绳`（包括字符和二进制字符串）。

-   `校对标识`：直方图数据的排序规则 ID。当`数据类型`值为`细绳`.值对应`ID`列中的值[`INFORMATION_SCHEMA.COLLATIONS`](information-schema-collations-table.html)桌子。

    要从直方图对象中提取特定值，您可以使用[`JSON`](json.html)操作。例如：


```
mysql> SELECT
         TABLE_NAME, COLUMN_NAME,
         HISTOGRAM->>'$."data-type"' AS 'data-type',
         JSON_LENGTH(HISTOGRAM->>'$."buckets"') AS 'bucket-count'
       FROM INFORMATION_SCHEMA.COLUMN_STATISTICS;
+-----------------+-------------+-----------+--------------+
| TABLE_NAME      | COLUMN_NAME | data-type | bucket-count |
+-----------------+-------------+-----------+--------------+
| country         | Population  | int       |          226 |
| city            | Population  | int       |         1024 |
| countrylanguage | Language    | string    |          457 |
+-----------------+-------------+-----------+--------------+
```

如果适用，优化器将直方图统计信息用于收集统计信息的任何数据类型的列。优化器根据列值与常量值比较的选择性（过滤效果）应用直方图统计信息来确定行估计。这些形式的谓词有资格使用直方图：

```
col_name = constant
col_name <> constant
col_name != constant
col_name > constant
col_name < constant
col_name >= constant
col_name <= constant
col_name IS NULL
col_name IS NOT NULL
col_name BETWEEN constant AND constant
col_name NOT BETWEEN constant AND constant
col_name IN (constant[, constant] ...)
col_name NOT IN (constant[, constant] ...)
```

例如，这些语句包含有资格使用直方图的谓词：

```
SELECT * FROM orders WHERE amount BETWEEN 100.0 AND 300.0;
SELECT * FROM tbl WHERE col1 = 15 AND col2 > 100;
```

与常数值进行比较的要求包括常数函数，例如[`ABS()`](mathematical-functions.html#function_abs)和[`地面（）`](mathematical-functions.html#function_floor)：

```
SELECT * FROM tbl WHERE col1 < ABS(-34);
```

直方图统计信息主要用于非索引列。将索引添加到直方图统计信息适用的列也可能有助于优化器进行行估计。权衡是：

-   修改表数据时必须更新索引。

-   直方图仅根据需要创建或更新，因此在修改表数据时不会增加开销。另一方面，当发生表修改时，统计信息会逐渐过时，直到下次更新。

    与从直方图统计中获得的估计相比，优化器更喜欢范围优化器的行估计。如果优化器确定范围优化器适用，则不使用直方图统计信息。

    对于被索引的列，可以使用索引潜水获得行估计以进行相等比较（请参阅[第 8.2.1.2 节，“范围优化”](range-optimization.html)）。在这种情况下，直方图统计不一定有用，因为指数潜水可以产生更好的估计。

    在某些情况下，使用直方图统计信息可能不会改进查询执行（例如，如果统计信息已过期）。要检查是否是这种情况，请使用[`分析表`](analyze-table.html)重新生成直方图统计信息，然后再次运行查询。

    或者，要禁用直方图统计信息，请使用[`分析表`](analyze-table.html)放下它们。禁用直方图统计的另一种方法是关闭[`条件扇出过滤器`](switchable-optimizations.html#optflag_condition-fanout-filter)国旗[`优化器开关`](server-system-variables.html#sysvar_optimizer_switch)系统变量（尽管这也可能会禁用其他优化）：


```
SET optimizer_switch='condition_fanout_filter=off';
```

如果使用直方图统计，则结果效果是可见的[`解释`](explain.html).考虑以下查询，其中没有可用于列的索引`col1`：

```
SELECT * FROM t1 WHERE col1 < 24;
```

如果直方图统计表明 57% 的行在`t1`满足`col1 < 24`谓词，即使没有索引也可以进行过滤，并且[`解释`](explain.html)显示 57.00 在`过滤`柱子。
