#### 8.10.2.2 多键缓存

笔记

从 MySQL 8.0 开始，此处讨论的复合部分结构化变量语法用于引用多个`MyISAM`密钥缓存已弃用。

对密钥缓存的共享访问可以提高性能，但不能完全消除会话之间的争用。他们仍然在争夺管理对关键缓存缓冲区的访问的控制结构。为了进一步减少 key 缓存访问争用，MySQL 还提供了多个 key 缓存。此功能使您可以将不同的表索引分配给不同的键缓存。

在有多个键缓存的情况下，服务器必须知道在处理给定查询时使用哪个缓存`MyISAM`桌子。默认情况下，所有`MyISAM`表索引缓存在默认键缓存中。要将表索引分配给特定的键缓存，请使用[`缓存索引`](cache-index.html)声明（见[第 13.7.8.2 节，“CACHE INDEX 语句”](cache-index.html)）。例如，以下语句从表中分配索引`t1`,`t2`， 和`t3`到名为的密钥缓存`热缓存`：

```
mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
+---------+--------------------+----------+----------+
| Table   | Op                 | Msg_type | Msg_text |
+---------+--------------------+----------+----------+
| test.t1 | assign_to_keycache | status   | OK       |
| test.t2 | assign_to_keycache | status   | OK       |
| test.t3 | assign_to_keycache | status   | OK       |
+---------+--------------------+----------+----------+
```

中提到的密钥缓存[`缓存索引`](cache-index.html)可以通过设置其大小来创建语句[`设置全球`](set-variable.html)参数设置语句或通过使用服务器启动选项。例如：

```
mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;
```

要销毁密钥缓存，请将其大小设置为零：

```
mysql> SET GLOBAL keycache1.key_buffer_size=0;
```

您不能销毁默认密钥缓存。任何这样做的尝试都会被忽略：

```
mysql> SET GLOBAL key_buffer_size = 0;

mysql> SHOW VARIABLES LIKE 'key_buffer_size';
+-----------------+---------+
| Variable_name   | Value   |
+-----------------+---------+
| key_buffer_size | 8384512 |
+-----------------+---------+
```

键缓存变量是具有名称和组件的结构化系统变量。为了`keycache1.key_buffer_size`,`密钥缓存1`是缓存变量名和[`key_buffer_size`](server-system-variables.html#sysvar_key_buffer_size)是缓存组件。看[第 5.1.9.5 节，“结构化系统变量”](structured-system-variables.html)，用于描述用于引用结构化密钥缓存系统变量的语法。

默认情况下，表索引分配给在服务器启动时创建的主（默认）键缓存。当一个键缓存被销毁时，分配给它的所有索引都会重新分配给默认的键缓存。

对于繁忙的服务器，您可以使用涉及三个键缓存的策略：

-   一个“热”键缓存，占用分配给所有键缓存的空间的 20%。将此用于大量用于搜索但未更新的表。

-   一个“冷”键缓存，占用为所有键缓存分配的空间的 20%。将此高速缓存用于中型、密集修改的表，例如临时表。

-   占用 60% 的密钥缓存空间的“暖”密钥缓存。将此用作默认键缓存，默认情况下用于所有其他表。

    使用三个键缓存有益的一个原因是对一个键缓存结构的访问不会阻止对其他键缓存结构的访问。访问分配给一个缓存的表的语句不会与访问分配给另一个缓存的表的语句竞争。性能提升也有其他原因：

-   热缓存仅用于检索查询，因此它的内容永远不会被修改。因此，每当需要从磁盘中拉入索引块时，不需要先刷新选择用于替换的缓存块的内容。

-   对于分配给热缓存的索引，如果没有查询需要索引扫描，则索引B树的非叶子节点对应的索引块很有可能保留在缓存中。

-   当更新的节点在缓存中并且不需要首先从磁盘读取时，对临时表执行最频繁的更新操作执行得更快。如果临时表的索引大小与冷键缓存的大小相当，则更新节点在缓存中的概率很高。

    这[`缓存索引`](cache-index.html)语句在表和键缓存之间建立关联，但每次服务器重新启动时关联都会丢失。如果您希望关联在每次服务器启动时生效，实现此目的的一种方法是使用选项文件：包括配置密钥缓存的变量设置，以及[`初始化文件`](server-system-variables.html#sysvar_init_file)命名文件的系统变量包含[`缓存索引`](cache-index.html)要执行的语句。例如：


```
key_buffer_size = 4G
hot_cache.key_buffer_size = 2G
cold_cache.key_buffer_size = 2G
init_file=/path/to/data-directory/mysqld_init.sql
```

中的陈述`mysqld_init.sql`每次服务器启动时执行。该文件应每行包含一个 SQL 语句。以下示例将多个表分别分配给`热缓存`和`冷缓存`：

```
CACHE INDEX db1.t1, db1.t2, db2.t3 IN hot_cache
CACHE INDEX db1.t4, db2.t5, db2.t6 IN cold_cache
```
