文档首页
MySQL NDB Cluster API 开发者指南
相关文档 下载本手册
PDF (US Ltr) - 3.6Mb
PDF (A4) - 3.6Mb


2.1.3.2 NDB API 处理 MySQL 数据类型

本节介绍 MySQL 数据类型在 NDBCLUSTER 表列中的表示方式,以及如何在 NDB API 应用程序中访问这些值。

数值数据类型。 MySQL TINYINTSMALLINTINTBIGINT 数据类型映射到 NDB 类型,它们与 MySQL 对应类型的名称和存储要求相同。

MySQL FLOATDOUBLE 数据类型映射到 NDB 类型,它们与 MySQL 对应类型的名称和存储要求相同。

用于字符数据的类型。 MySQL CHAR 列所需的存储空间由最大字符数和列的字符集决定。对于大多数(但并非全部)字符集,每个字符占用一个字节的存储空间。当使用 utf8 时,每个字符需要三个字节;utfmb4 使用最多四个字节来存储每个字符。您可以通过检查 SHOW CHARACTER SET 输出的 Maxlen 列,找到给定字符集中每个字符需要的最大字节数。

一个 NDB VARCHAR 列值映射到 MySQL VARCHAR,但 NDB VARCHAR 的前两个字节保留用于字符串的长度。像这里显示的实用程序函数可以使 VARCHAR 值准备好在 NDB API 应用程序中使用

void make_ndb_varchar(char *buffer, char *str)
{
  int len = strlen(str);
  int hlen = (len > 255) ? 2 : 1;
  buffer[0] = len & 0xff;
  if( len > 255 )
    buffer[1] = (len / 256);
  strcpy(buffer+hlen, str);
}

您可以像这里显示的示例一样使用该函数

char myVal[128+1]; // Size of myVal (+1 for length)
...
make_ndb_varchar(myVal, "NDB is way cool!!");
myOperation->setValue("myVal", myVal);

有关使用 NDB API 将 VARCHARVARBINARY 值写入和读取表的完整示例程序,请参见 第 2.5.12 节“NDB API 简单数组示例”

MySQL 对 VARCHARVARBINARY 列的存储要求取决于列是在内存中存储还是在磁盘上存储

  • 对于内存中的列,NDB 存储引擎支持宽度可变的列,并进行 4 字节对齐。这意味着(例如)使用 latin1 字符集存储在 VARCHAR(50) 列中的字符串 'abcde' 需要 12 个字节 - 在这种情况下,2 个字节乘以 5 个字符为 10,向上舍入到最接近的 4 的倍数,得到 12。

  • 对于磁盘数据列,VARCHARVARBINARY 作为宽度固定的列存储。这意味着这些类型中的每一个都需要与相同大小的 CHAR 相同的存储空间。

注意

在本 指南 中,我们始终将 MySQL 的任何 TEXTBLOB 类型中的列称为 blob 列,其类型称为 blob。NDB 7.5 及更高版本也将 MySQL JSON 列视为 blob 列。

NDB Cluster BLOBTEXT 列中的每一行都由两个独立的部分组成。其中一个部分大小固定(256 字节),实际上存储在原始表中。另一部分包含超过 256 字节的所有数据,存储在一个隐藏的 blobs 表中,该表的行始终为 2000 字节长。这意味着 TEXTBLOB 列中大小为 size 字节的记录需要

  • 256 个字节,如果 size <= 256

  • 256 + 2000 * ((size – 256) \ 2000) + 1) 字节,否则

时间数据类型。 时间类型在 NDB API 中的存储方式取决于使用的是没有小数秒的 MySQL 类型还是支持小数秒的 类型。对小数秒的支持是在 MySQL 5.6 以及基于它的 NDB Cluster 版本中引入的 - 即 NDB 7.3 和 NDB 7.4。这些版本以及更高版本的 MySQL Server 和 NDB Cluster 默认使用新的时间类型,可以读取和写入使用旧时间类型的数据,但不能创建使用旧类型的表。有关更多信息,请参见 时间值中的小数秒

由于预计在未来版本中会删除对旧时间类型的支持,因此建议您将所有使用旧时间类型的表迁移到这些类型的新版本。您可以通过对使用旧时间的任何表执行复制 ALTER TABLE 操作来实现这一点,或者通过备份和还原所有这样的表来实现这一点。

您可以通过检查 NDB Cluster 发行版提供的 ndb_desc 实用程序的输出,查看给定表是使用旧时间类型还是新时间类型。假设在一个名为 test 的数据库中,使用以下语句在未使用 --create-old-temporals 选项启动的 mysqld 上创建了一个表

CREATE TABLE t1 (
    c1 DATETIME,
    c2 DATE,
    c3 TIME,
    c4 TIMESTAMP,
    c5 YEAR) ENGINE=NDB;

ndb_desc 输出的相关部分(Attributes 块)如下所示

$> ndb_desc -dtest t1
...
-- Attributes --
c1 Datetime2(0) NULL AT=FIXED ST=MEMORY
c2 Date NULL AT=FIXED ST=MEMORY
c3 Time2(0) NULL AT=FIXED ST=MEMORY
c4 Timestamp2(0) NOT NULL AT=FIXED ST=MEMORY DEFAULT 0
c5 Year NULL AT=FIXED ST=MEMORY

新的 MySQL 时间类型的名称以 2 为后缀(例如,Datetime2),以将其与这些类型的旧版本区分开来。假设我们使用 --create-old-temporals=ON 选项重新启动 mysqld,然后使用以下语句创建表 t2,该表也在 test 数据库中

CREATE TABLE t2 (
    c1 DATETIME,
    c2 DATE,
    c3 TIME,
    c4 TIMESTAMP,
    c5 YEAR) ENGINE=NDB;

对该表执行 ndb_desc 所示的输出包含这里显示的 Attributes

$> ndb_desc -dtest t2
...
-- Attributes --
c1 Datetime NULL AT=FIXED ST=MEMORY
c2 Date NULL AT=FIXED ST=MEMORY
c3 Time NULL AT=FIXED ST=MEMORY
c4 Timestamp NOT NULL AT=FIXED ST=MEMORY DEFAULT 0
c5 Year NULL AT=FIXED ST=MEMORY

受影响的 MySQL 类型是 TIMEDATETIMETIMESTAMP。这些类型的“新”版本在 NDB API 中分别反映为 Time2Datetime2Timestamp2,每个都支持小数秒,精度最高可达 6 位。新的变体使用整数值的 Big-Endian 编码,然后处理这些编码以确定每种时间类型的分量。

对于这些类型中每个类型的小数秒部分,精度会影响所需的字节数,如下表所示

表 2.2 NDB API 新时间类型的精度

精度 所需字节 范围
0 0
1 1 0-9
2 1 0-99
3 2 0-999
4 2 0-9999
5 3 0-99999
6 3 0-999999

每种新的时间类型的分数部分以 Big-Endian 格式存储,即最高位字节位于最低地址处,使用必要的字节数。

接下来几段将介绍这些类型的新旧版本的二进制布局。

Time:此类型的“旧”版本存储为一个 24 位有符号 int 值,以 Little-Endian 格式存储(最低位字节位于最低位地址)。字节 0(位 0-7)对应小时,字节 2(位 8-15)对应分钟,字节 2(位 16-23)对应秒,公式如下

value =   10000 * hour
        + 100 * minute
        + second

位 23 用作符号位;如果设置了此位,则时间值被认为是负数。

Time2:这是“新”的 TIME 类型,存储为一个 3 字节 Big-Endian 编码值加上 0 到 3 字节的分数部分。整数部分的编码方式如下表所示

表 2.3 Time2 编码

含义 范围
23 符号位 0-1
22 间隔 0-1
22-13 小时 1-1023
12-7 分钟 0-63
6-0 0-63

除了这个之外的任何分数字节都按之前描述的方式处理。

Date:MySQL DATE 类型的表示在 NDB 版本之间保持不变,并且使用一个以 Little-Endian 顺序存储的 3 字节无符号整数。编码方式如下所示

表 2.4 日期编码

含义 范围
23-9 0-32767
8-5 0-15
4-0 0-31

Datetime:“旧”的 MySQL DATETIME 类型由一个 64 位无符号值表示,以主机字节序存储,使用以下公式进行编码

value   = second
        + minute  * 102
        + hour    * 104
        + day     * 106
        + month   * 108
        + year    * 1010

DateTime2:“新”的 DATETIME 被编码为一个 5 字节 Big-Endian,带有一个可选的分数部分,范围为 0 到 3 字节,分数部分按之前描述的方式处理。最高 5 个字节的编码方式如下所示

表 2.5 DateTime2 编码

含义 范围
23 符号位 0-1
22 间隔 0-1
22-13 小时 1-1023
12-7 分钟 0-63
6-0 0-63

YearMonth 位被编码为 Year = YearMonth / 13Month = YearMonth % 13

Timestamp:此类型的“旧”版本使用一个 32 位无符号值,表示自 Unix 纪元开始以来的秒数,以主机字节序存储。

Timestamp2:这是“新”版本的 TIMESTAMP,使用 4 个字节,以 Big-Endian 编码表示整数部分(无符号)。可选的 3 字节分数部分的编码方式如本节前面所述。

附加信息。ndb/src/common/util/NdbSqlUtil.cpp 中可以找到更多关于数据类型以及在 NDB API 中表达数据类型的示例信息。此外,请参阅第 2.5.14 节,“Timestamp2 示例”,其中提供了一个使用 Timestamp2 数据类型的简单 NDB API 应用程序示例。