15.1.20.12 设置 NDB 注释选项
NDB 集群中可以在表注释或列注释中设置特定的选项。使用 NDB_TABLE 可以将控制从任何副本读取和分区平衡的表级选项嵌入到表注释中。
NDB_COLUMN 可以在列注释中设置 NDB 对 blob 值的部分表列的大小,以存储 blob 值的最大值。这适用于BLOB、MEDIUMBLOB、LONGBLOB、TEXT、MEDIUMTEXT、LONGTEXT 和JSON 列。列注释也可以控制 blob 列的内联大小。NDB_COLUMN 注释不支持 TINYBLOB 或 TINYTEXT 列,因为这些列只有固定大小的内联部分,且没有其他地方存储。
NDB_TABLE 可以在表注释中设置与分区平衡和是否完全复制等选项。
本节余下部分描述这些选项及其用法。
在 NDB 集群中,CREATE TABLE 或 ALTER TABLE 语句中的列注释也可以用来指定一个 NDB_COLUMN 选项。NDB 支持两个列注释选项 BLOB_INLINE_SIZE 和 MAX_BLOB_PART_SIZE。这些选项的语法在这里展示:
COMMENT 'NDB_COLUMN=speclist'
speclist := spec[,spec]
spec :=
BLOB_INLINE_SIZE=value
| MAX_BLOB_PART_SIZE[={0|1}]
BLOB_INLINE_SIZE 指定了列存储的字节数;其预期值是一个介于 1 - 29980 之间的整数。设置大于 29980 的值会引发错误;设置小于 1 的值允许,但将使用该列类型的默认内联大小。
您应该注意,这个选项的最大值实际上是 NDB 表中每行可以存储的字节数;每个列都对这个总数进行贡献。
特别是在使用 TEXT 列时,设置的 MAX_BLOB_PART_SIZE 或 BLOB_INLINE_SIZE 值表示列大小以字节为单位,不是字符数,这个值根据列使用的字符集和排序规则而变化。
要查看这个选项的效果,首先创建一个包含两个 BLOB 列的表,其中一个 (b1) 没有额外选项,另一个 (b2) 设置了 BLOB_INLINE_SIZE,如下所示:
mysql> CREATE TABLE t1 (
-> a INT NOT NULL PRIMARY KEY,
-> b1 BLOB,
-> b2 BLOB COMMENT 'NDB_COLUMN=BLOB_INLINE_SIZE=8000'
-> ) ENGINE NDB;
Query OK, 0 rows affected (0.32 sec)
您可以通过查询ndbinfo.blobs表来查看BLOB_INLINE_SIZE设置,例如:
mysql> SELECT
-> column_name AS 'Column Name',
-> inline_size AS 'Inline Size',
-> part_size AS 'Blob Part Size'
-> FROM ndbinfo.blobs
-> WHERE table_name = 't1';
+-------------+-------------+----------------+
| Column Name | Inline Size | Blob Part Size |
+-------------+-------------+----------------+
| b1 | 256 | 2000 |
| b2 | 8000 | 2000 |
+-------------+-------------+----------------+
2 rows in set (0.01 sec)
您也可以检查ndb_desc实用工具的输出,像这样,以高亮显示相关行:
$> ndb_desc -d test t1
-- t --
Version: 1
Fragment type: HashMapPartition
K Value: 6
Min load factor: 78
Max load factor: 80
Temporary table: no
Number of attributes: 3
Number of primary keys: 1
Length of frm data: 945
Max Rows: 0
Row Checksum: 1
Row GCI: 1
SingleUserMode: 0
ForceVarPart: 1
PartitionCount: 2
FragmentCount: 2
PartitionBalance: FOR_RP_BY_LDM
ExtraRowGciBits: 0
ExtraRowAuthorBits: 0
TableStatus: Retrieved
Table options: readbackup
HashMap: DEFAULT-HASHMAP-3840-2
-- Attributes --
a Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
b1 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_64_1
b2 Blob(8000,2000,0) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_64_2
-- Indexes --
PRIMARY KEY(a) - UniqueHashIndex
PRIMARY(a) - OrderedIndex
对于MAX_BLOB_PART_SIZE,=符号和其后的值是可选的。使用除0或1以外的任何值都会导致语法错误。
使用MAX_BLOB_PART_SIZE在列注释中,设置TEXT或BLOB列的 blob 部分大小为 NDB 支持的最大字节数(13948)。这项选项可以应用于 MySQL 中除TINYBLOB或TINYTEXT(BLOB,MEDIUMBLOB,LONGBLOB,TEXT,MEDIUMTEXT,LONGTEXT)以外的所有 blob 列类型。与BLOB_INLINE_SIZE不同的是,MAX_BLOB_PART_SIZE对JSON列无效。
要查看这个选项的效果,我们首先在mysql 客户端中运行以下 SQL 语句,创建一个包含两个 BLOB 列的表,其中一个 (c1) 没有额外选项,另一个 (c2) 有 MAX_BLOB_PART_SIZE:
mysql> CREATE TABLE test.t2 (
-> p INT PRIMARY KEY,
-> c1 BLOB,
-> c2 BLOB COMMENT 'NDB_COLUMN=MAX_BLOB_PART_SIZE'
-> ) ENGINE NDB;
Query OK, 0 rows affected (0.32 sec)
从系统 shell 中运行ndb_desc 工具,获取刚创建的表的信息,如下所示:
$> ndb_desc -d test t2
-- t --
Version: 1
Fragment type: HashMapPartition
K Value: 6
Min load factor: 78
Max load factor: 80
Temporary table: no
Number of attributes: 3
Number of primary keys: 1
Length of frm data: 324
Row Checksum: 1
Row GCI: 1
SingleUserMode: 0
ForceVarPart: 1
FragmentCount: 2
ExtraRowGciBits: 0
ExtraRowAuthorBits: 0
TableStatus: Retrieved
HashMap: DEFAULT-HASHMAP-3840-2
-- Attributes --
p Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
c1 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_22_1
c2 Blob(256,13948,0) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_22_2
-- Indexes --
PRIMARY KEY(p) - UniqueHashIndex
PRIMARY(p) - OrderedIndex
输出中的列信息在 Attributes 下面列出;对于 c1 和 c2,这里以加粗显示。对于 c1,blob 部分大小为 2000,是默认值;对于 c2,是由 MAX_BLOB_PART_SIZE 设置的 13948。
你也可以查询 ndbinfo.blobs 表来查看,如下所示:
mysql> SELECT
-> column_name AS 'Column Name',
-> inline_size AS 'Inline Size',
-> part_size AS 'Blob Part Size'
-> FROM ndbinfo.blobs
-> WHERE table_name = 't2';
+-------------+-------------+----------------+
| Column Name | Inline Size | Blob Part Size |
+-------------+-------------+----------------+
| c1 | 256 | 2000 |
| c2 | 256 | 13948 |
+-------------+-------------+----------------+
2 rows in set (0.00 sec)
你可以使用一个类似于以下的 ALTER TABLE 语句来更改某个 blob 列的 blob 部分大小,然后使用SHOW CREATE TABLE 来验证变化:
mysql> ALTER TABLE test.t2
-> DROP COLUMN c1,
-> ADD COLUMN c1 BLOB COMMENT 'NDB_COLUMN=MAX_BLOB_PART_SIZE',
-> CHANGE COLUMN c2 c2 BLOB AFTER c1;
Query OK, 0 rows affected (0.47 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SHOW CREATE TABLE test.t2\G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE `t2` (
`p` int(11) NOT NULL,
`c1` blob COMMENT 'NDB_COLUMN=MAX_BLOB_PART_SIZE',
`c2` blob,
PRIMARY KEY (`p`)
) ENGINE=ndbcluster DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
mysql> EXIT
Bye
ndb_desc 的输出显示,blob 部分大小已经如期更改了:
$> ndb_desc -d test t2
-- t --
Version: 16777220
Fragment type: HashMapPartition
K Value: 6
Min load factor: 78
Max load factor: 80
Temporary table: no
Number of attributes: 3
Number of primary keys: 1
Length of frm data: 324
Row Checksum: 1
Row GCI: 1
SingleUserMode: 0
ForceVarPart: 1
FragmentCount: 2
ExtraRowGciBits: 0
ExtraRowAuthorBits: 0
TableStatus: Retrieved
HashMap: DEFAULT-HASHMAP-3840-2
-- Attributes --
p Int PRIMARY KEY DISTRIBUTION KEY AT=FIXED ST=MEMORY
c1 Blob(256,13948,0) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_26_1
c2 Blob(256,2000,0) NULL AT=MEDIUM_VAR ST=MEMORY BV=2 BT=NDB$BLOB_26_2
-- Indexes --
PRIMARY KEY(p) - UniqueHashIndex
PRIMARY(p) - OrderedIndex
你也可以通过运行查询语句对ndbinfo.blobs来查看变化:
mysql> SELECT
-> column_name AS 'Column Name',
-> inline_size AS 'Inline Size',
-> part_size AS 'Blob Part Size'
-> FROM ndbinfo.blobs
-> WHERE table_name = 't2';
+-------------+-------------+----------------+
| Column Name | Inline Size | Blob Part Size |
+-------------+-------------+----------------+
| c1 | 256 | 13948 |
| c2 | 256 | 2000 |
+-------------+-------------+----------------+
2 rows in set (0.00 sec)
可以同时设置BLOB_INLINE_SIZE和MAX_BLOB_PART_SIZE对blob列,如下所示的CREATE TABLE语句:
mysql> CREATE TABLE test.t3 (
-> p INT NOT NULL PRIMARY KEY,
-> c1 JSON,
-> c2 JSON COMMENT 'NDB_COLUMN=BLOB_INLINE_SIZE=5000,MAX_BLOB_PART_SIZE'
-> ) ENGINE NDB;
Query OK, 0 rows affected (0.28 sec)
查询blobs表显示该语句如预期工作:
mysql> SELECT
-> column_name AS 'Column Name',
-> inline_size AS 'Inline Size',
-> part_size AS 'Blob Part Size'
-> FROM ndbinfo.blobs
-> WHERE table_name = 't3';
+-------------+-------------+----------------+
| Column Name | Inline Size | Blob Part Size |
+-------------+-------------+----------------+
| c1 | 4000 | 8100 |
| c2 | 5000 | 8100 |
+-------------+-------------+----------------+
2 rows in set (0.00 sec)
你也可以通过检查ndb_desc的输出来验证该语句是否工作。
更改blob列的部分大小必须使用复制ALTER TABLE;这不能在线执行(见第25.6.12节,“NDB集群中的在线ALTER TABLE操作”)。
关于NDB如何存储blob类型列的信息,见字符串类型存储要求。
对于 NDB 集群表,CREATE TABLE 或ALTER TABLE 语句中也可以使用表注释来指定一个 NDB_TABLE 选项,该选项由一个或多个名称-值对,使用逗号分隔,如果需要,可以在字符串NDB_TABLE=后面添加。名称和值的完整语法在这里展示:
COMMENT="NDB_TABLE=ndb_table_option[,ndb_table_option[,...]]"
ndb_table_option: {
NOLOGGING={1 | 0}
| READ_BACKUP={1 | 0}
| PARTITION_BALANCE={FOR_RP_BY_NODE | FOR_RA_BY_NODE | FOR_RP_BY_LDM
| FOR_RA_BY_LDM | FOR_RA_BY_LDM_X_2
| FOR_RA_BY_LDM_X_3 | FOR_RA_BY_LDM_X_4}
| FULLY_REPLICATED={1 | 0}
}
不允许在引号内出现空格。该字符串是大小写不敏感。
下面四个 NDB 表选项可以作为注释的一部分设置,详细描述在下文几段中。
NOLOGGING:默认情况下,NDB 表是被记录的,并且在检查点。使用 NOLOGGING 创建或修改表时,这个表不再记录redo日志,也不包括本地检查点。在这种情况下,该表仍然在数据节点之间复制,使用事务更新,但是对该表的更改不被记录到数据节点的redo日志中,也不将其内容写入磁盘;当从集群故障恢复时,集群保留表定义,但没有行—that 是,表为空。
使用这种非日志表减少数据节点对磁盘I/O和存储的需求,同时也减少了checkpointing CPU。对于短暂更新频繁的数据,如果总集群故障时丢失所有数据是可接受的,这可能是一个选择。
还可以使用ndb_table_no_logging系统变量,使得在该变量生效期间创建或修改的NDB表表现为被创建时带有NOLOGGING注释。与直接使用注释不同,在这种情况下,SHOW CREATE TABLE的输出中不会出现该表是非日志表的信息。使用表注释方法推荐,因为它提供了每个表的控制权,并且这个表架构方面嵌入在创建语句中,可以被SQL基于工具轻松找到。
READ_BACKUP: 将该选项设置为 1,效果等同于启用ndb_read_backup,允许从任何副本读取。这样可以大幅提高对表的读性能,但写性能会有较小的损失。默认值为 READ_BACKUP,ndb_read_backup 的默认值是 ON(之前,默认情况下不允许从任何副本读取)。
可以在线为已有表设置 READ_BACKUP,使用类似于以下所示的ALTER TABLE 语句:
ALTER TABLE ... ALGORITHM=INPLACE, COMMENT="NDB_TABLE=READ_BACKUP=1";
ALTER TABLE ... ALGORITHM=INPLACE, COMMENT="NDB_TABLE=READ_BACKUP=0";
关于第25.6.12节,“NDB 集群中的在线 ALTER TABLE” 中的 ALGORITHM 选项有更多信息。
PARTITION_BALANCE: 提供分区的分配和存储控制。支持以下四种方案:
-
FOR_RP_BY_NODE: 每个节点一个分区。每个节点上只有一个 LDM 存储主分区,每个分区在所有节点上都存储在同一个 LDM(同一 ID)中。
-
FOR_RA_BY_NODE:每个节点组一个分区。每个节点存储一个分区,可以是主副本或备份副本。每个分区都存储在所有节点的同一个LDM中。
-
FOR_RP_BY_LDM:每个节点每个LDM一个分区,缺省值。如果
READ_BACKUP设置为1,则使用这个设置。 -
FOR_RA_BY_LDM:每个节点组每个LDM一个分区。这些分区可以是主分区或备份分区。
-
FOR_RA_BY_LDM_X_2:每个节点组每个LDM两个分区。这些分区可以是主分区或备份分区。
-
FOR_RA_BY_LDM_X_3:每个节点组每个LDM三个分区。这些分区可以是主分区或备份分区。
-
FOR_RA_BY_LDM_X_4:每个节点组每个LDM四个分区。这些分区可以是主分区或备份分区。
PARTITION_BALANCE 是设置表中分区数量的首选接口。使用MAX_ROWS强制设置分区数量虽然已经弃用,但仍然继续支持,以便于向后兼容;将来MySQL NDB 集群的某个版本中可能移除(Bug #81759,Bug #23544301)。
FULLY_REPLICATED 控制表是否完全复制,即每个数据节点都有表的完整副本。要启用表的完全复制,使用FULLY_REPLICATED=1。
此设置也可以使用ndb_fully_replicated系统变量控制。将其设置为ON默认启用该选项对所有新创建的NDB表;默认是OFF。同时,ndb_data_node_neighbour系统变量也用于完全复制表,以确保当访问完全复制表时,我们访问该 MySQL 服务器的数据节点。
创建一个使用这种注释的CREATE TABLE语句的示例,如下所示:
mysql> CREATE TABLE t1 (
> c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
> c2 VARCHAR(100),
> c3 VARCHAR(100) )
> ENGINE=NDB
>
COMMENT="NDB_TABLE=READ_BACKUP=0,PARTITION_BALANCE=FOR_RP_BY_NODE";
注释作为SHOW CREATE TABLE语句的输出的一部分。注释文本也可以从查询 MySQL 信息_schemaTABLES表中获取,例如:
mysql> SELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT
> FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1"\G
*************************** 1. row ***************************
TABLE_NAME: t1
TABLE_SCHEMA: test
TABLE_COMMENT: NDB_TABLE=READ_BACKUP=0,PARTITION_BALANCE=FOR_RP_BY_NODE
1 row in set (0.01 sec)
这种注释语法也支持在ALTER TABLE语句中用于NDB表,如下所示:
mysql> ALTER TABLE t1 COMMENT="NDB_TABLE=PARTITION_BALANCE=FOR_RA_BY_NODE";
Query OK, 0 rows affected (0.40 sec)
Records: 0 Duplicates: 0 Warnings: 0
TABLE_COMMENT 列显示了在执行ALTER TABLE语句后要重新创建的表注释,如下:
mysql> SELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT
-> FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1"\G
*************************** 1. row ***************************
TABLE_NAME: t1
TABLE_SCHEMA: test
TABLE_COMMENT: NDB_TABLE=READ_BACKUP=0,PARTITION_BALANCE=FOR_RP_BY_NODE
1 row in set (0.01 sec)
mysql> SELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT
> FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1";
+------------+--------------+--------------------------------------------------+
| TABLE_NAME | TABLE_SCHEMA | TABLE_COMMENT |
+------------+--------------+--------------------------------------------------+
| t1 | c | NDB_TABLE=PARTITION_BALANCE=FOR_RA_BY_NODE |
| t1 | d | |
+------------+--------------+--------------------------------------------------+
2 rows in set (0.01 sec)
请注意,使用ALTER TABLE语句时的表注释将替换该表可能有的任何现有注释。
mysql> ALTER TABLE t1 COMMENT="NDB_TABLE=PARTITION_BALANCE=FOR_RA_BY_NODE";
Query OK, 0 rows affected (0.40 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT
> FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1";
+------------+--------------+--------------------------------------------------+
| TABLE_NAME | TABLE_SCHEMA | TABLE_COMMENT |
+------------+--------------+--------------------------------------------------+
| t1 | c | NDB_TABLE=PARTITION_BALANCE=FOR_RA_BY_NODE |
| t1 | d | |
+------------+--------------+--------------------------------------------------+
2 rows in set (0.01 sec)
您也可以在ndb_desc的输出中看到PARTITION_BALANCE选项的值。ndb_desc还显示了表是否设置了READ_BACKUP和FULLY_REPLICATED选项。请查看该程序的描述以获取更多信息。