使用 Interval Fragment 子句存储通过一个或多个计算为数字或 INTERVAL 数据类型的范围表达式定义的行。在您为一个分片指定至少一个非 NULL 范围后,数据库服务器在插入分片键值超出现有分片的范围的行的 DML 操作中自动创建新的间隔分片。
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
dbspace | 存储分片的 dbspace 名称 | 最多只能指定 2,048 个 dbspaces 。所有存储分片的 dbspaces 必须具有相同的页面大小。 | 标识符 |
dbspace _fun | 返回 dbspace 的名称的 UDF | 当数据库服务器调用 UDR 为新分片分配存储时,用户定义的函数以及返回的 dbspace 必须存在 | CREATE FUNCTION 语句 |
intvl_ valexpr | 在分片键范围捏定义间隔大小的间隔值表达式 | 必须是与分片键表达式的数据类型符合的求值为数字或 INTERVAL 值的常量字符表达式 | 标识符 |
partition | 此处为范围分片声明的名称 | 在同一表的分片名称中必须是唯一的。如果表和它的索引使用同一范围间隔分片策略,则每个索引分片必须具有与对应表分片相同的名称。 | 标识符 |
range _expr | 定义分片中分片键的上限的常量表达式 | 必须是与分片键表达式的数据类型符合的求值为数字或 INTERVAL 值的常量字符表达式 | 常量表达式 |
Interval Fragment 子句定义紧跟在 FRAGMENT BY 子句的 FRAGMENT BY RANGE 关键字之后指定的分片键表达式范围内的一个或多个非重叠的间隔。PARTITION BY RANGE 关键字是 FRAGMENT BY RANGE 关键字的同义词。如果向表中插入或更改符合为此分片定义的范围的 DML 操作,那么数据库服务器将新的或更改的行存储在那个分片中。
必须定义指示一个分片以存储具有非 NULL 分片键值的行。对于分片键值为 NULL 的行不需要定义分片。但是如果没有为 NULL 值定义分片,则对表会产生带有 NULL 分片键值的 DML 操作会失败。
Interval Fragment 子句无法定义 remainder 分片。
INTERVAL 关键字之后的 intvl_valexpr 表达式定义在分片键值范围内的分片的大小。
您可以使用字符数值或者字符 INTERVAL 值作为 intvl_valexpr 表达式。还可以使用内置的 NUMTODSINTERVAL 、NUMTOYMINTERVAL 、TO_DSINTERVAL 或 TO_YMINTERVAL 函数指定 intvl_valexpr 表达式。有关这些函数的语法和在 Interval Fragment 子句中使用它们的示例,请参阅 TO_YMINTERVAL 函数 和 TO_DSINTERVAL 函数。
如果您没有指定 intvl_valexpr 表达式,则禁用间隔分片的自动创建功能,但是 INTERVAL 关键字之后仍需要空的括号来避免语法错误。
当 DML 操作存储分片键值超出现有分片范围的行时,紧随 STORE IN 关键字之后的 dbspace (或以逗号分隔的 dbspace 名称列表)为服务器自动创建的新的间隔分片标识存储空间。如果您指定多个 dbspace ,则数据库服务器在 STORE IN 子句中指定的 dbspace 的循环分布方案中创建间隔分片,并为此新的分片声明系统生成的名称。
当创建表或索引时,不需要显示 STORE IN 子句中的 dbspace 。您可以在创建表或索引后向系统中添加 dbspace。所有 Interval Fragment 子句中引用的 dbspace 必须具有相同的页大小。
如果您省略了 STORE IN 子句, 且表需要存储超出现有分片和范围分片的行时,数据库服务器自动在范围表达式分片的 PARTITION 规范列表的 dbspace 的循环分布方案中创建新的间隔分片。
STORE IN 子句可以可选地指定一个返回现有 dbspace 名称的用户定义的函数,而不是文本 dbspace 标识符列表。您为此 UDF 声明的标识符是任意的。
然而,当您在 STORE IN 子句中引用任意 UDR 时,不要给 UDF 指定任何参数。它所需要的仅是 UDF 名称,紧随在一对空括号之后,像以上语法图中所指示的那样。数据库服务器自动在调用时自动提供参数。
CREATE FUNCTION mydbname ( owner CHAR(255), table CHAR(255), value DATE, -- Data type must match or must be compatible -- with the data type of the fragment key retry INTEGER ) RETURNING CHAR(255) IF (retry > 0) THEN RETURN NULL; -- This UDF does not handle retries: if the first call -- fails, an invalid dbspace is returned, and the DML -- statement that requires a new fragment also fails. END IF; IF (MONTH(value) < 7) THEN RETURN "dbs1"; ELSE RETURN "dbs2"; END IF; END FUNCTION; CREATE TABLE orders ( order_num SERIAL(1001), order_date DATE, customer_num INTEGER NOT NULL, ship_instruct CHAR(40), backlog CHAR(1), po_num CHAR(10), ship_date DATE, ship_weight DECIMAL(8,2), ship_charge MONEY(6), paid_date DATE ) PARTITION BY RANGE(order_date) INTERVAL(1 UNITS MONTH) STORE IN (mydbname()) PARTITION prv_partition VALUES < DATE("01/01/2010") IN mydbs;
当需要为此表创建新的间隔分片时,数据库服务器定义指定的函数。如果在返回的 dbspace 中尝试创建分片失败,则用 retry 标记设置第二次调用相同的函数,以致于会返回一个不同的现有 dbspace 名称。第二次尝试失败后,执行的 DML 语句返回错误。(如果第一次尝试失败,则以上示例中的 UDF 不会进行第二次尝试,但是返回 NULL ,一个无效的 dbspace 名称。)
如果范围分片没有按升序顺序定义,则数据库服务器按升序顺序存储它们,因此在第一个初始位置的分片具有最小的上限范围。
在相同的 Interval Fragment 子句中的两个分片不能具有相同的上限。 PARTITION 规范中定义的范围分片不能重叠。如果(intvl_valexpr)大小规范在 INTERVAL 关键字之后, 那么如果定义连续范围分片的范围表达式之间的差异与 INTERVAL 大小规范不同,则数据库服务器发出错误。
NULL 分片并非必需,但如果用户尝试擦汗荣分片键值是 NULL 的行,而不存在 NULL 分片时,数据库服务器返回错误。
dbschema -ss 命令的输出显示了通过范围间隔分布方案分片的表的结构,该方案只返回用户在 CREATE TABLE 或 ALTER FRAGMENT 语句中的定义的范围分片。
此情况同样对于 dbexport -ss 命令的输出同样为真。
当您使用 Interval Fragment 子句定义表或索引的范围分片时,不需要知道分片键值的全部范围。当插入一个不适合范围分片或间隔分片的行是,数据库服务器自动创建新的间隔分片来存储该行(基于间隔 intvl_valexp,不用 DBA 干预)。
表或索引的间隔分区的系统生成的名称是 sys_evalpos,evalpos 是系统目录中的此分片 sysfragments.evalpos 条目。如果表和它的索引使用相同的范围间隔分片策略,每个系统生成的索引分片将具有与该表的系统生成的分片相同的标识符。
这些自动生成的分片对应于包括新数据值的分片键范围的部分。如果在两个连续分片之间大于 intvl_valexp 范围的一部分不包含行,则间隙可以自动生成间隔分片。但是,在您在 Interval Fragment 子句中显式定义的分片之间是不允许间隙的。
如果未指定 intvl_valexp 表达式,则在 Interval Fragment 子句中显式定义的范围分片可用于存储在其范围间隔内具有对应分片键值的行,以及在禁用 ALTER FRAGMENT 以及之前生成的任何现有间隔分片自动创建间隔分片。然而,在这两种情况中,禁用自动创建新分片。如果用户尝试插入分片键值不在现有分片范围内的行,则数据库服务器发出错误 -772,并插入失败。
如上所述,dbschema -ss 和 dbexport -ss 命令显示按范围间隔分片的表的模式的输出仅包括用户定义的范围分片。在输出显示中不会显示系统生成的间隔分片。
以下示例使用 INT 列 cust_id 的值作为数字分片键,并定义了四个范围分片。数据库服务器将为 cust_id 值超过 7999999 的插入行创建间隔大小是 1000000 的间隔发分片:
CREATE TABLE customer (cust_id INT, name CHAR (128), street CHAR (1024), state CHAR (2), zipcode CHAR (5), phone CHAR (12)) FRAGMENT BY RANGE (cust_id) INTERVAL (1000000) STORE IN (dbs2, dbs1) PARTITION p0 VALUES < 2000000 IN dbs1, PARTITION p1 VALUES < 4000000 IN dbs1, PARTITION p2 VALUES < 6000000 IN dbs2, PARTITION p3 VALUES < 8000000 IN dbs3;
在以下 DATETIME 分片键示例中,如果 dt1 列的值超过 VALUES 子句指定的范围分片的界限,则将在 25 年间隔中在 2005 年之后的 dbs1 dbspace 中创建间隔分片:
CREATE TABLE t1 (c1 int, d1 date, dt1 DATETIME YEAR TO FRACTION) FRAGMENT BY RANGE (dt1) INTERVAL (INTERVAL(25) YEAR(2) TO YEAR) PARTITION p1 VALUES < DATETIME(2006-01-01 00:00:00.00000) YEAR TO FRACTION(5) IN dbs1;
在下一个示例中,DATE 列 order_date 的值是分片键,并且定义了四个范围分片,包括 order_date 具有 NULL 值的行的 p4。对于 order_date 的年值晚于 2007 的插入行,将在 01/01/2008 之后的 1 个月内自动创建间隔分片,并在 dbs1 、dbs2 和 dbs3 dbspace 中创建连续分片:
CREATE TABLE orders (order_id INT, cust_id INT, order_date DATE, order_desc CHAR (1024)) FRAGMENT BY RANGE (order_date) INTERVAL (NUMTOYMINTERVAL (1,'MONTH')) STORE IN (dbs1, dbs2, dbs3) PARTITION p0 VALUES < DATE ('01/01/2005') IN dbs1, PARTITION p1 VALUES < DATE ('01/01/2006') IN dbs1, PARTITION p2 VALUES < DATE ('01/01/2007') IN dbs2, PARTITION p3 VALUES < DATE ('01/01/2008') IN dbs3, PARTITION p4 VALUES IS NULL in dbs3;
下一个 DATE 分片键的示例与先前的示例类似,但是此处的间隔大小指定为 1.5 年。在 12/31/2009 之后,对于 order_date 值,将以 18 个月(1.5 年)的间隔创建间隔分片:
CREATE TABLE orders1 (order_id INT, cust_id INT, order_date DATE, order_desc CHAR (1024)) FRAGMENT BY RANGE (order_date) INTERVAL (NUMTOYMINTERVAL (1.5,'YEAR')) 000STORE IN (dbs1, dbs2, dbs3) PARTITION p0 VALUES < DATE ('01/01/2004') IN dbs1, PARTITION p1 VALUES < DATE ('01/01/2006') IN dbs1, PARTITION p2 VALUES < DATE ('01/01/2008') IN dbs2, PARTITION p3 VALUES < DATE ('01/01/2010') IN dbs3;如果 order_date 值丢失,则不能将行插入 orders1 表。因为没有定义非 NULL 分片。有关向现有使用范围间隔分片的表中添加 NULL 分片的语法,请参阅 ALTER FRAGMENT 语句的 ADD 子句主题。