#### 23.6.10.1 NDB Cluster 磁盘数据对象

NDB Cluster 磁盘数据存储使用以下对象实现：

-   表空间：充当其他磁盘数据对象的容器。一个表空间包含一个或多个数据文件和一个或多个撤消日志文件组。

-   数据文件：存储列数据。数据文件直接分配给表空间。

-   撤消日志文件：包含回滚事务所需的撤消信息。分配给撤消日志文件组。

-   日志文件组：包含一个或多个撤消日志文件。分配给一个表空间。

    撤消日志文件和数据文件是每个数据节点的文件系统中的实际文件；默认情况下，它们被放置在`ndb_*`node_id`*_fs`在里面*`数据目录`*在 NDB Cluster 中指定`配置文件`文件，以及在哪里*`node_id`*是数据节点的节点 ID。在创建撤消日志或数据文件时，可以通过将绝对或相对路径指定为文件名的一部分来将它们放置在其他位置。创建这些文件的语句将在本节后面显示。

    撤消日志文件仅由磁盘数据表使用，不需要或由`新开发银行`仅存储在内存中的表。

    NDB Cluster 表空间和日志文件组未实现为文件。

    尽管并非所有磁盘数据对象都作为文件实现，但它们都共享相同的命名空间。这意味着*每个磁盘数据对象*必须唯一命名（而不仅仅是给定类型的每个磁盘数据对象）。例如，您不能同时命名一个表空间和一个日志文件组`dd1`.

    假设您已经建立了一个包含所有节点（包括管理节点和 SQL 节点）的 NDB Cluster，那么在磁盘上创建 NDB Cluster 表的基本步骤如下：

[](<>)

1.  创建一个日志文件组，并为其分配一个或多个撤消日志文件（撤消日志文件有时也称为撤消文件）。

2.  创建表空间；将日志文件组以及一个或多个数据文件分配给表空间。

3.  创建一个使用该表空间进行数据存储的磁盘数据表。

    这些任务中的每一个都可以使用 SQL 语句完成[**mysql**](mysql.html)客户端或其他 MySQL 客户端应用程序，如下面的示例所示。

4.  [](<>)我们创建一个名为的日志文件组`lg_1`使用[`创建日志文件组`](create-logfile-group.html).这个日志文件组由两个 undo 日志文件组成，我们将它们命名为`undo_1.log`和`undo_2.log`，其初始大小分别为 16 MB 和 12 MB。（撤消日志文件的默认初始大小为 128 MB。）您也可以选择为日志文件组的撤消缓冲区指定大小，或允许它采用默认值 8 MB。在本例中，我们将 UNDO 缓冲区的大小设置为 2 MB。必须使用撤消日志文件创建日志文件组；所以我们添加`undo_1.log`到`lg_1`在这[`创建日志文件组`](create-logfile-group.html)陈述：

    ```
    CREATE LOGFILE GROUP lg_1
        ADD UNDOFILE 'undo_1.log'
        INITIAL_SIZE 16M
        UNDO_BUFFER_SIZE 2M
        ENGINE NDBCLUSTER;
    ```

    添加`undo_2.log`到日志文件组，使用以下[`更改日志文件组`](alter-logfile-group.html)陈述：

    ```
    ALTER LOGFILE GROUP lg_1
        ADD UNDOFILE 'undo_2.log'
        INITIAL_SIZE 12M
        ENGINE NDBCLUSTER;
    ```

    一些注意事项：

    -   这`。日志`此处使用的文件扩展名不是必需的。我们使用它只是为了使日志文件易于识别。

    -   每一个[`创建日志文件组`](create-logfile-group.html)和[`更改日志文件组`](alter-logfile-group.html)声明必须包括`引擎`选项。此选项的唯一允许值是[`NDBCLUSTER`](mysql-cluster.html)和[`新开发银行`](mysql-cluster.html).

        重要的

        在任何给定时间，同一 NDB Cluster 中最多可以存在一个日志文件组。

    -   当您使用将撤消日志文件添加到日志文件组时`添加撤销文件'*`文件名`*'`, 一个文件名*`文件名`*是在`ndb_*`node_id`*_fs`内的目录[`数据目录`](mysql-cluster-ndbd-definition.html#ndbparam-ndbd-datadir)集群中的每个数据节点，其中*`node_id`*是数据节点的节点 ID。每个撤消日志文件的大小在 SQL 语句中指定。例如，如果 NDB Cluster 有 4 个数据节点，则[`更改日志文件组`](alter-logfile-group.html)刚刚显示的语句创建了 4 个撤消日志文件，每个文件在 4 个数据节点的数据目录中打开；这些文件中的每一个都被命名`undo_2.log`每个文件大小为 12 MB。

    -   `UNDO_BUFFER_SIZE`受可用系统内存量的限制。

    -   看[第 13.1.16 节，“CREATE LOGFILE GROUP 语句”](create-logfile-group.html)， 和[第 13.1.6 节，“ALTER LOGFILE GROUP 语句”](alter-logfile-group.html), 有关这些声明的更多信息。

5.  [](<>)现在我们可以创建一个表空间——磁盘数据表用来存储数据的文件的抽象容器。一个表空间与一个特定的日志文件组相关联；创建新表空间时，您必须指定它用于撤消日志记录的日志文件组。您还必须指定至少一个数据文件；创建表空间后，您可以向表空间添加更多数据文件。也可以从表空间中删除数据文件（参见本节后面的示例）。

    假设我们希望创建一个名为`ts_1`哪个使用`lg_1`作为其日志文件组。我们希望表空间包含两个数据文件，名为`数据_1.dat`和`数据_2.dat`，其初始大小分别为 32 MB 和 48 MB。（默认值为`INITIAL_SIZE`是 128 MB。）我们可以使用两个 SQL 语句来做到这一点，如下所示：

    ```
    CREATE TABLESPACE ts_1
        ADD DATAFILE 'data_1.dat'
        USE LOGFILE GROUP lg_1
        INITIAL_SIZE 32M
        ENGINE NDBCLUSTER;

    ALTER TABLESPACE ts_1
        ADD DATAFILE 'data_2.dat'
        INITIAL_SIZE 48M;
    ```

    这[`创建表空间`](create-tablespace.html)语句创建表空间`ts_1`与数据文件`数据_1.dat`, 和同事`ts_1`带日志文件组`lg_1`.这[`改变表空间`](alter-tablespace.html)添加第二个数据文件（`数据_2.dat`）。

    一些注意事项：

    -   与`。日志`本例中用于 undo 日志文件的文件扩展名，没有特殊意义`.dat`文件扩展名;它仅用于易于识别。

    -   当您使用将数据文件添加到表空间时`添加数据文件'*`文件名`*'`, 一个文件名*`文件名`*是在`ndb_*`node_id`*_fs`内的目录[`数据目录`](mysql-cluster-ndbd-definition.html#ndbparam-ndbd-datadir)集群中的每个数据节点，其中*`node_id`*是数据节点的节点 ID。每个数据文件的大小在 SQL 语句中指定。例如，如果 NDB Cluster 有 4 个数据节点，则[`改变表空间`](alter-tablespace.html)刚才显示的语句创建了 4 个数据文件，4 个数据节点中每个数据节点的数据目录中各有 1 个；这些文件中的每一个都被命名`数据_2.dat`每个文件大小为 48 MB。

    -   `新开发银行`保留每个表空间的 4% 以供数据节点重新启动期间使用。此空间不可用于存储数据。

    -   [`创建表空间`](create-tablespace.html)语句必须包含`引擎`条款;只能在表空间中创建与表空间使用相同存储引擎的表。为了[`改变表空间`](alter-tablespace.html)， 一个`引擎`子句被接受，但已被弃用，并且在未来的版本中可能会被删除。为了`新开发银行`表空间，此选项唯一允许的值是`NDBCLUSTER`和`新开发银行`.

    -   在 NDB 8.0.20 及更高版本中，在给定表空间使用的所有数据文件中以循环方式执行范围的分配。

    -   有关更多信息[`创建表空间`](create-tablespace.html)和[`改变表空间`](alter-tablespace.html)陈述，见[第 13.1.21 节，“CREATE TABLESPACE 语句”](create-tablespace.html)， 和[第 13.1.10 节，“ALTER TABLESPACE 语句”](alter-tablespace.html).

6.  [](<>)现在可以使用表空间中的文件创建一个未索引列存储在磁盘上的表`ts_1`：

    ```
    CREATE TABLE dt_1 (
        member_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        last_name VARCHAR(50) NOT NULL,
        first_name VARCHAR(50) NOT NULL,
        dob DATE NOT NULL,
        joined DATE NOT NULL,
        INDEX(last_name, first_name)
        )
        TABLESPACE ts_1 STORAGE DISK
        ENGINE NDBCLUSTER;
    ```

      `表空间 ts_1 存储磁盘`告诉[`新开发银行`](mysql-cluster.html)使用表空间的存储引擎`ts_1`用于磁盘上的数据存储。

    一次表`ts_1`已创建如图所示，您可以执行[`插入`](insert.html), [`选择`](select.html), [`更新`](update.html)， 和[`删除`](delete.html)就像你对任何其他 MySQL 表一样。

    还可以通过使用`贮存`子句作为列定义的一部分[`创建表`](create-table.html)要么[`更改表`](alter-table.html)陈述。`存储磁盘`使列存储在磁盘上，并且`存储内存`导致使用内存中的存储。看[第 13.1.20 节，“CREATE TABLE 语句”](create-table.html)， 了解更多信息。

    您可以获取有关`新开发银行`通过查询刚刚创建的磁盘数据文件和撤消日志文件[`文件`](information-schema-files-table.html)表中的`INFORMATION_SCHEMA`数据库，如下所示：


```
mysql> SELECT
              FILE_NAME AS File, FILE_TYPE AS Type,
              TABLESPACE_NAME AS Tablespace, TABLE_NAME AS Name,
              LOGFILE_GROUP_NAME AS 'File group',
              FREE_EXTENTS AS Free, TOTAL_EXTENTS AS Total
          FROM INFORMATION_SCHEMA.FILES
          WHERE ENGINE='ndbcluster';
+--------------+----------+------------+------+------------+------+---------+
| File         | Type     | Tablespace | Name | File group | Free | Total   |
+--------------+----------+------------+------+------------+------+---------+
| ./undo_1.log | UNDO LOG | lg_1       | NULL | lg_1       |    0 | 4194304 |
| ./undo_2.log | UNDO LOG | lg_1       | NULL | lg_1       |    0 | 3145728 |
| ./data_1.dat | DATAFILE | ts_1       | NULL | lg_1       |   32 |      32 |
| ./data_2.dat | DATAFILE | ts_1       | NULL | lg_1       |   48 |      48 |
+--------------+----------+------------+------+------------+------+---------+
4 rows in set (0.00 sec)
```

有关更多信息和示例，请参阅[第 26.3.15 节，“信息\_架构文件表”](information-schema-files-table.html).

**隐式存储在磁盘上的列的索引。**餐桌用`dt_1`如刚刚显示的示例中所定义，只有`出生日期`和`加入`列存储在磁盘上。这是因为有索引`id`,`姓`， 和`名`列，因此属于这些列的数据存储在 RAM 中。只有非索引列可以保存在磁盘上；索引和索引列数据继续存储在内存中。在设计磁盘数据表时，您必须牢记在使用索引和节省 RAM 之间进行权衡。

您不能将索引添加到已显式声明的列`存储磁盘`，而无需先将其存储类型更改为`记忆`;任何这样做的尝试都会失败并出现错误。一列*含蓄地*使用可索引的磁盘存储；完成后，列的存储类型更改为`记忆`自动地。“隐式”是指未声明存储类型但从父表继承的列。在以下 CREATE TABLE 语句中（使用表空间`ts_1`先前定义），列`c2`和`c3`隐式使用磁盘存储：

```
mysql> CREATE TABLE ti (
    ->     c1 INT PRIMARY KEY,
    ->     c2 INT,
    ->     c3 INT,
    ->     c4 INT
    -> )
    ->     STORAGE DISK
    ->     TABLESPACE ts_1
    ->     ENGINE NDBCLUSTER;
Query OK, 0 rows affected (1.31 sec)
```

因为`c2`,`c3`， 和`c4`本身没有声明`存储磁盘`, 可以对它们进行索引。在这里，我们将索引添加到`c2`和`c3`, 分别使用,`创建索引`和`更改表`：

```
mysql> CREATE INDEX i1 ON ti(c2);
Query OK, 0 rows affected (2.72 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE ti ADD INDEX i2(c3);
Query OK, 0 rows affected (0.92 sec)
Records: 0  Duplicates: 0  Warnings: 0
```

[`显示创建表`](show-create-table.html)确认已添加索引。

```
mysql> SHOW CREATE TABLE ti\G
*************************** 1. row ***************************
       Table: ti
Create Table: CREATE TABLE `ti` (
  `c1` int(11) NOT NULL,
  `c2` int(11) DEFAULT NULL,
  `c3` int(11) DEFAULT NULL,
  `c4` int(11) DEFAULT NULL,
  PRIMARY KEY (`c1`),
  KEY `i1` (`c2`),
  KEY `i2` (`c3`)
) /*!50100 TABLESPACE `ts_1` STORAGE DISK */ ENGINE=ndbcluster DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
```

你可以看到使用[**数据库\_描述**](mysql-cluster-programs-ndb-desc.html)索引列（强调文本）现在使用内存而不是磁盘存储：

```
$> ./ndb_desc -d test t1
-- t1 --
Version: 33554433
Fragment type: HashMapPartition
K Value: 6
Min load factor: 78
Max load factor: 80
Temporary table: no
Number of attributes: 4
Number of primary keys: 1
Length of frm data: 317
Max Rows: 0
Row Checksum: 1
Row GCI: 1
SingleUserMode: 0
ForceVarPart: 1
PartitionCount: 4
FragmentCount: 4
PartitionBalance: FOR_RP_BY_LDM
ExtraRowGciBits: 0
ExtraRowAuthorBits: 0
TableStatus: Retrieved
Table options:
HashMap: DEFAULT-HASHMAP-3840-4
-- Attributes --
c1 Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
c2 Int NULL AT=FIXED ST=MEMORY
c3 Int NULL AT=FIXED ST=MEMORY
c4 Int NULL AT=FIXED ST=DISK
-- Indexes --
PRIMARY KEY(c1) - UniqueHashIndex
i2(c3) - OrderedIndex
PRIMARY(c1) - OrderedIndex
i1(c2) - OrderedIndex

NDBT_ProgramExit: 0 - OK
```

**性能说明。**如果将磁盘数据文件保存在与数据节点文件系统不同的物理磁盘上，则使用磁盘数据存储的集群的性能会大大提高。必须对集群中的每个数据节点执行此操作才能获得任何明显的好处。

您可以使用绝对和相对文件系统路径`添加撤销文件`和`添加数据文件`;相对路径是相对于数据节点的数据目录计算的。

必须以特定顺序创建日志文件组、表空间和使用这些的任何磁盘数据表。删除这些对象也是如此，但受以下约束：

[](<>)

-   只要有任何表空间使用日志文件组，就不能删除它。

-   只要表空间包含任何数据文件，就不能删除它。

-   只要还有任何正在使用该表空间的表，您就不能从表空间中删除任何数据文件。

-   不能删除与创建文件的表空间不同的表空间相关联的文件。

    例如，要删除本节到目前为止创建的所有对象，您可以使用以下语句：


```
mysql> DROP TABLE dt_1;

mysql> ALTER TABLESPACE ts_1
    -> DROP DATAFILE 'data_2.dat'
    -> ENGINE NDBCLUSTER;

mysql> ALTER TABLESPACE ts_1
    -> DROP DATAFILE 'data_1.dat'
    -> ENGINE NDBCLUSTER;

mysql> DROP TABLESPACE ts_1
    -> ENGINE NDBCLUSTER;

mysql> DROP LOGFILE GROUP lg_1
    -> ENGINE NDBCLUSTER;
```

这些语句必须按所示顺序执行，除了这两个`ALTER TABLESPACE ... 删除数据文件`语句可以按任意顺序执行。
