iha*_*nny 2 database data-integrity netezza
似乎缺乏对执行2个基本约束(唯一和外键)的支持,是失去许多工时调试和解决难题的原因.什么开始是一个简单,易于修复的问题(重复行/不一致的主要细节表)在我们的应用程序中甚至在我们的硬件中都没有被注意到,增长并引发复杂的边缘场景(例如,自我加入与重复可能导致通货膨胀和储存耗尽).
任何人都可以推荐一种方法/工具来避免这些麻烦吗?
我知道有一个公认的答案,但我想提供一种替代方法.对我目前的职位不熟悉,我并不了解仓库中主要关键声明背后的所有业务决策.我开发了日志记录类型方法来跟踪重复行删除工作.以下是此设计的主要功能:
以下是Netezza视角所需的一切.需要注意的是,您需要填补空白以创建动态SQL.
首先,我创建了一个跟踪所有重复记录的数据库,表和内部rowid的表.
CREATE TABLE
NZ_DUPLICATE_PKS
(
DATABASE_NAME CHARACTER VARYING(128) NOT NULL
,TABLE_OWNER CHARACTER VARYING(128) NOT NULL
,TABLE_NAME CHARACTER VARYING(128) NOT NULL
,ROW_ID BIGINT NOT NULL
,CURRENT_RECORD_INDICATOR CHARACTER(1) NOT NULL
,CREATE_TIMESTAMP TIMESTAMP NOT NULL
,LAST_UPDATE_TIMESTAMP TIMESTAMP NOT NULL
)
DISTRIBUTE ON
(
ROW_ID
);
Run Code Online (Sandbox Code Playgroud)
注意:分配键上的YMMV和进入表的行数.我们Netezza应用程序中的行ID具有甚至足够的自然分布,它在基于野马的NPS 10050上很好地服务于我.
接下来,创建了此表的暂存版本:
CREATE TABLE
STG_NZ_DUPLICATE_PKS
(
DATABASE_NAME CHARACTER VARYING(128)
,TABLE_OWNER CHARACTER VARYING(128)
,TABLE_NAME CHARACTER VARYING(128)
,ROW_ID BIGINT
,CURRENT_RECORD_INDICATOR CHARACTER(1)
,CREATE_TIMESTAMP TIMESTAMP
,LAST_UPDATE_TIMESTAMP TIMESTAMP
)
DISTRIBUTE ON
(
ROW_ID
);
Run Code Online (Sandbox Code Playgroud)
然后,我从系统视图创建了动态查询,以便为登台表提供种子.这是我开始的基本查询:
SELECT
DATABASE
,OWNER
,RELATION
,CONSTRAINTNAME
,ATTNAME
FROM
{YOUR_DATABASE_NAME}._V_RELATION_KEYDATA
WHERE
CONTYPE = 'p'
-- Exclude the duplicate tracking table
AND RELATION != 'NZ_DUPLICATE_PKS'
ORDER BY
DATABASE
,OWNER
,RELATION
,CONSTRAINTNAME
,CONSEQ
;
Run Code Online (Sandbox Code Playgroud)
现在我遍历基本查询以动态创建插入查询.我的商店使用的是DataStage,它的方法很深奥,不值得在这里阐述.
注意:这是循环和构造动态SQL所需的一些工作.可以使用无数种shell,Perl,Python等.使用带有两个列键的示例表,下面是构造用于插入登台表的内容:
INSERT
INTO
STG_NZ_DUPLICATE_PKS
(
DATABASE_NAME
,TABLE_OWNER
,TABLE_NAME
,ROW_ID
,CURRENT_RECORD_INDICATOR
,CREATE_TIMESTAMP
,LAST_UPDATE_TIMESTAMP
)
SELECT
'{YOUR_DATABASE_NAME}' DATABASE_NAME
,'{YOUR_TABLE_OWNER}' TABLE_OWNER
,'{YOUR_TABLE_NAME}' TABLE_NAME
,DUPS.ROWID ROW_ID
,'Y' CURRENT_RECORD_INDICATOR
,CURRENT_TIMESTAMP CREATE_TIMESTAMP
,CURRENT_TIMESTAMP LAST_UPDATE_TIMESTAMP
FROM
{YOUR_TABLE_NAME} DUPS
INNER JOIN
(
SELECT
{KEY_COLUMN_1}
,{KEY_COLUMN_2}
FROM
{YOUR_TABLE_NAME}
GROUP BY
{KEY_COLUMN_1}
,{KEY_COLUMN_2}
HAVING
COUNT(*) > 1
)
KEYS
ON
DUPS.{KEY_COLUMN_1} = KEYS.{KEY_COLUMN_1}
AND DUPS.{KEY_COLUMN_2} = KEYS.{KEY_COLUMN_2};
Run Code Online (Sandbox Code Playgroud)
循环遍历所有表以对登台表进行播种后,然后运行一系列查询,将数据库,所有者,表名和行ID视为缓慢变化的维度.此查询结束日期目标表中的记录,这些记录在登台表中不存在:
UPDATE
NZ_DUPLICATE_PKS
SET
CURRENT_RECORD_INDICATOR = 'N'
,LAST_UPDATE_TIMESTAMP = CURRENT_TIMESTAMP
WHERE
CURRENT_RECORD_INDICATOR = 'Y'
AND
(
DATABASE_NAME
,TABLE_OWNER
,TABLE_NAME
,ROW_ID
)
NOT IN
(
SELECT
DATABASE_NAME
,TABLE_OWNER
,TABLE_NAME
,ROW_ID
FROM
STG_NZ_DUPLICATE_PKS
)
;
Run Code Online (Sandbox Code Playgroud)
最后,将最新记录插入目标表:
INSERT
INTO
NZ_DUPLICATE_PKS
(
DATABASE_NAME
,TABLE_OWNER
,TABLE_NAME
,ROW_ID
,CURRENT_RECORD_INDICATOR
,CREATE_TIMESTAMP
,LAST_UPDATE_TIMESTAMP
)
SELECT
DATABASE_NAME
,TABLE_OWNER
,TABLE_NAME
,ROW_ID
,CURRENT_RECORD_INDICATOR
,CREATE_TIMESTAMP
,LAST_UPDATE_TIMESTAMP
FROM
STG_NZ_DUPLICATE_PKS
WHERE
(
DATABASE_NAME
,TABLE_OWNER
,TABLE_NAME
,ROW_ID
)
NOT IN
(
SELECT
DATABASE_NAME
,TABLE_OWNER
,TABLE_NAME
,ROW_ID
FROM
NZ_DUPLICATE_PKS
WHERE
CURRENT_RECORD_INDICATOR = 'Y'
)
;
Run Code Online (Sandbox Code Playgroud)
注意:我们的环境不是必须使用仅插入模型.Netezza老将会熟悉这种思路.如果您的环境是仅插入的,请相应地调整策略.
一切就绪后,找到重复的行进行调查是很容易的:
SELECT
*
FROM
{YOUR_TABLE_NAME}
WHERE
ROWID IN
(
SELECT
ROW_ID
FROM
NZ_DUPLICATE_PKS
WHERE
CURRENT_RECORD_INDICATOR = 'Y'
AND DATABASE_NAME = '{YOUR_DATABASE_NAME}'
AND TABLE_OWNER = '{YOUR_OWNER_NAME}'
AND TABLE_NAME = '{YOUR_TABLE_NAME}'
);
Run Code Online (Sandbox Code Playgroud)
我喜欢这个,因为它对所有表都很简单和相同,无论主键声明有什么不同.
我也经常使用这个查询来查看表中当前的主键违规:
SELECT
DATABASE_NAME
,TABLE_OWNER
,TABLE_NAME
,COUNT(*) QUANTITY
FROM
NZ_DUPLICATE_PKS
WHERE
CURRENT_RECORD_INDICATOR = 'Y'
GROUP BY
1
,2
,3
ORDER BY
1
,2
,3;
Run Code Online (Sandbox Code Playgroud)
这总结了一切.我希望有些人觉得它很有用.我们已经通过这种方法取得了很多进展.在这一点上,你可能想知道我为什么遇到这些麻烦.我讨厌允许PK违规进入我们的仓库,我希望采取全面的方法来消灭它们.上述过程每天都在我们的生产环境中运行几个月.我们有大约350个声明主键的表,大小从5行到大约2亿行事实@ 10Gb.对于Netezza来说,这是一个非常适度的支出.我们的野马NPS 10050整个过程不到10分钟.