2.1.3.2 NDB API 处理 MySQL 数据类型

本节提供有关 MySQL 数据类型在 NDBCLUSTER 表列中的表示方式以及如何在 NDB API 应用程序中访问这些值的信息。

数字数据类型。  MySQL TINYINTSMALLINTINTBIGINT数据类型映射到 NDB与其对应的 MySQL 具有相同名称和存储要求的类型。

MySQLFLOATDOUBLE数据类型映射到 NDB具有相同名称和存储要求的类型。

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

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 向表写入和读取 值 的完整示例程序, 请参阅第 2.5.12 节,“NDB API 简单数组示例” 。VARCHARVARBINARY

VARCHARMySQL 对or 列 的存储要求 VARBINARY取决于该列是存储在内存中还是磁盘上:

  • 对于内存中的列,NDB 存储引擎支持具有 4 字节对齐的可变宽度列。这意味着(例如) 'abcde'存储在 VARCHAR(50)使用字符集的列中的 字符串latin1需要 12 个字节——在这种情况下,2 个字节乘以 5 个字符是 10,四舍五入到下一个 4 的偶数倍数得到 12。

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

笔记

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

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

  • 256 字节,如果size <= 256

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

时间数据类型。  NDB API 中时间类型的存储取决于是使用 MySQL 的不带小数秒的类型还是使用带小数秒支持的类型。在 MySQL 5.6 以及基于它的 NDB Cluster 版本(即 NDB 7.3 和 NDB 7.4)中引入了对小数秒的支持。这些版本默认使用新的临时类型,但可以通过启动mysqld来使用旧的 --create-old-temporals=ON. NDB 7.5及之后的版本——也就是那些基于MySQL 5.7及之后的NDB Cluster版本——可以使用旧的时间类型读写数据,但是不能创建使用旧类型的表。有关 MySQL 服务器中这些更改的更多信息, 请参阅时间值中的小数秒。

因为在未来的版本中预计会删除对旧时态类型的支持,所以我们鼓励您将使用旧时态类型的任何表迁移到这些类型的新版本。您可以通过 ALTER TABLE使用旧时间对任何表执行复制操作,或通过备份和恢复任何此类表来实现这一点。

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

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),以将它们与这些类型的旧版本区分开来。假设我们重新启动mysqld--create-old-temporals=ON然后使用以下语句t2test 数据库中创建一个表:

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

如图所示,在此表上 执行ndb_descAttributes的输出包括此处显示的块:

$> 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 位的小数秒。新变体使用整数值的大端编码,然后对其进行处理以确定每个时间类型的组件。

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

表 2.1 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

每个新时间类型的小数部分都以大端格式存储——也就是说,最高位字节在最低地址——使用必要的字节数。

这些类型的新旧版本的二进制布局在接下来的几段中描述。

Time:此类型的版本存储为以小端格式存储的 24 位有符号int值(最低​​位地址中的最低位字节)。根据以下公式,字节 0(位 0-7)对应小时,字节 2(位 8-15)对应分钟,字节 2(位 16-23)对应秒:

value =   10000 * hour
        + 100 * minute
        + second

第 23 位作为符号位;如果该位被设置,时间值被认为是负的。

Time2:这是 NDB 7.3 和 7.4(MySQL 5.6)中添加的 TIME类型,存储为 3 字节 big-endian 编码值加上小数部分的 0 到 3 字节。整数部分编码如下表所示:

表 2.2 Time2 编码

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

除此之外的任何小数字节都按前面所述进行处理。

Date:MySQL DATE类型的表示在 NDB 版本中保持不变,并使用以小端顺序存储的 3 字节无符号整数。编码如下所示:

表 2.3 日期编码

意义 范围
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

DateTime2new DATETIME被编码为 5 字节 big-endian,带有 0 到 3 字节的可选小数部分,小数部分的处理如前所述。高 5 字节的编码如下所示:

表 2.4 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在 NDB 7.3 和 7.4 (MySQL 5.6) 中实现的版本,并使用 4 个字节和 big-endian eoncoding 整数部分(无符号)。可选的 3 字节小数部分按照本节前面的说明进行编码。

附加信息。  有关 NDB API 中表示的 uding 数据类型的更多信息和示例,请参见 ndb/src/common/util/NdbSqlUtil.cpp。此外,请参阅第 2.5.14 节,“Timestamp2 示例”,它提供了一个使用Timestamp2数据类型的简单 NDB API 应用程序的示例。