在 Teradata 中为具有 one-to-one 关系的表插入策略
Insert strategy for tables with one-to-one relationships in Teradata
在源自 Teradata 行业模型的数据模型中,我们观察到一种常见模式,其中逻辑数据模型中的超类和子类关系被转换为 one-to-one [=44] 之间的关系=] 和 child table。
我知道您可以 roll-up 或 roll-down 属性以单个 table 结束,但我们总体上不使用此选项。最后我们得到的是这样一个模型:
其中城市 ID 引用地理区域 ID。
我正在努力寻找一个好的策略来加载这些 table 中的记录。
选项 1: 我可以 select max(Geographical Area Id) 并计算批量插入的下一个 ID,并将它们重新用于城市 Table.
选项 2: 我可以在地理区域中使用身份列 Table 并在插入每条记录后检索它,以便将其用于城市 table.
还有其他选择吗?
我需要从性能、可靠性和维护方面评估解决方案。
如有任何意见,我们将不胜感激。
亲切的问候,
保罗
当您说 "load the records into these tables" 时,您是在谈论一次性数据迁移还是为新地理 Area/City 创建记录的功能?
如果您要查找代理键并且可以接受 ID 值中的间隙,则使用 IDENTITY 列并指定 NO CYCLE 子句,这样它就不会重复任何数字。然后把值传NULL,让TD来处理。
如果您确实需要顺序 ID,那么您只需维护一个单独的 "NextId" table 并使用它来生成 ID 值。这是最灵活的方式,可以让您更轻松地管理 BATCH 操作。它需要更多 code/maintenance,但比对数据 table 执行 MAX() + 1 以获得下一个 ID 值更有效。基本思路如下:
开始交易
- 通过查找获取 "next" ID table
- 使用该值为您的下一条记录生成新的 ID 值
- 创造你的新记录
- 更新查找 table 中的 "next" ID 值并将其增加新插入的 # 行(您可以通过直接将值存储在 ACTIVITY_COUNT 值变量中来捕获它在执行你的 INSERT/MERGE 语句后)
- 确保在交易开始时锁定查找 table,以便在交易完成之前无法修改它
结束交易
这是一个来自 Postgres 的例子,你可以适应 TD:
CREATE TABLE NextId (
IDType VARCHAR(50) NOT NULL,
NextValue INTEGER NOT NULL,
PRIMARY KEY (IDType)
);
INSERT INTO Users(UserId, UserType)
SELECT
COALESCE(
src.UserId, -- Use UserId if provided (i.e. update existing user)
ROW_NUMBER() OVER(ORDER BY CASE WHEN src.UserId IS NULL THEN 0 ELSE 1 END ASC) +
(id.NextValue - 1) -- Use newly generated UserId (i.e. create new user)
)
AS UserIdFinal,
src.UserType
FROM (
-- Bulk Upsert (get source rows from JSON parameter)
SELECT src.FirstName, src.UserId, src.UserType
FROM JSONB_TO_RECORDSET(pUserDataJSON->'users') AS src(FirstName VARCHAR(100), UserId INTEGER, UserType CHAR(1))
) src
CROSS JOIN (
-- Get next ID value to use
SELECT NextValue
FROM NextId
WHERE IdType = 'User'
FOR UPDATE -- Use "Update" row-lock so it is not read by any other queries also using "Update" row-lock
) id
ON CONFLICT(UserId) DO UPDATE SET
UserType = EXCLUDED.UserType;
-- Increment UserId value
UPDATE NextId
SET NextValue = NextValue + COALESCE(NewUserCount,0)
WHERE IdType = 'User'
;
只需将锁定语句更改为 Teradata 语法(LOCK TABLE NextId FOR WRITE)并在 INSERT/MERGE 之后添加一个 ACTIVITY_COUNT 变量以捕获受影响的 # 行。这假设您在存储过程中执行所有这些操作。
告诉我进展如何...
在源自 Teradata 行业模型的数据模型中,我们观察到一种常见模式,其中逻辑数据模型中的超类和子类关系被转换为 one-to-one [=44] 之间的关系=] 和 child table。
我知道您可以 roll-up 或 roll-down 属性以单个 table 结束,但我们总体上不使用此选项。最后我们得到的是这样一个模型:
其中城市 ID 引用地理区域 ID。
我正在努力寻找一个好的策略来加载这些 table 中的记录。
选项 1: 我可以 select max(Geographical Area Id) 并计算批量插入的下一个 ID,并将它们重新用于城市 Table.
选项 2: 我可以在地理区域中使用身份列 Table 并在插入每条记录后检索它,以便将其用于城市 table.
还有其他选择吗?
我需要从性能、可靠性和维护方面评估解决方案。
如有任何意见,我们将不胜感激。
亲切的问候,
保罗
当您说 "load the records into these tables" 时,您是在谈论一次性数据迁移还是为新地理 Area/City 创建记录的功能?
如果您要查找代理键并且可以接受 ID 值中的间隙,则使用 IDENTITY 列并指定 NO CYCLE 子句,这样它就不会重复任何数字。然后把值传NULL,让TD来处理。
如果您确实需要顺序 ID,那么您只需维护一个单独的 "NextId" table 并使用它来生成 ID 值。这是最灵活的方式,可以让您更轻松地管理 BATCH 操作。它需要更多 code/maintenance,但比对数据 table 执行 MAX() + 1 以获得下一个 ID 值更有效。基本思路如下:
开始交易
- 通过查找获取 "next" ID table
- 使用该值为您的下一条记录生成新的 ID 值
- 创造你的新记录
- 更新查找 table 中的 "next" ID 值并将其增加新插入的 # 行(您可以通过直接将值存储在 ACTIVITY_COUNT 值变量中来捕获它在执行你的 INSERT/MERGE 语句后)
- 确保在交易开始时锁定查找 table,以便在交易完成之前无法修改它
结束交易
这是一个来自 Postgres 的例子,你可以适应 TD:
CREATE TABLE NextId (
IDType VARCHAR(50) NOT NULL,
NextValue INTEGER NOT NULL,
PRIMARY KEY (IDType)
);
INSERT INTO Users(UserId, UserType)
SELECT
COALESCE(
src.UserId, -- Use UserId if provided (i.e. update existing user)
ROW_NUMBER() OVER(ORDER BY CASE WHEN src.UserId IS NULL THEN 0 ELSE 1 END ASC) +
(id.NextValue - 1) -- Use newly generated UserId (i.e. create new user)
)
AS UserIdFinal,
src.UserType
FROM (
-- Bulk Upsert (get source rows from JSON parameter)
SELECT src.FirstName, src.UserId, src.UserType
FROM JSONB_TO_RECORDSET(pUserDataJSON->'users') AS src(FirstName VARCHAR(100), UserId INTEGER, UserType CHAR(1))
) src
CROSS JOIN (
-- Get next ID value to use
SELECT NextValue
FROM NextId
WHERE IdType = 'User'
FOR UPDATE -- Use "Update" row-lock so it is not read by any other queries also using "Update" row-lock
) id
ON CONFLICT(UserId) DO UPDATE SET
UserType = EXCLUDED.UserType;
-- Increment UserId value
UPDATE NextId
SET NextValue = NextValue + COALESCE(NewUserCount,0)
WHERE IdType = 'User'
;
只需将锁定语句更改为 Teradata 语法(LOCK TABLE NextId FOR WRITE)并在 INSERT/MERGE 之后添加一个 ACTIVITY_COUNT 变量以捕获受影响的 # 行。这假设您在存储过程中执行所有这些操作。
告诉我进展如何...