別のアプローチに貢献したかったのですが、受け入れられた答えがあることは理解しています。現在の役職に就いたばかりの私は、倉庫内の主キー宣言の背後にあるすべてのビジネス上の決定に関与しているわけではありません。重複行の削除作業を経時的に追跡するロギング タイプのアプローチを開発しました。このデザインの主な特徴は次のとおりです。
- DDL / DML の流動的な性質に対処し、常に最新の状態に保つ
- 新しい/削除されたテーブル
- 新規/更新された主キー
- 新規/更新/削除された行
- 自己入力履歴
- 経時的な改善を追跡
- すべてのレベルでトレンド分析の基礎を提供
- 調査目的でターゲット テーブルを簡単にクエリする
- HAVING 句による自己結合やキー列のルックアップは不要
- 現時点では主キーのみに対応
- Unique 制約に対処するために簡単に拡張できます (CONTYPE = 'u' in _V_RELATION_KEYDATA)
以下は、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
);
注: 分散キーの YMMV と、テーブルに入る行のボリューム。私たちの Netezza アプリケーションの行 ID は、Mustang ベースの 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
);
次に、システム ビューから動的クエリを作成して、ステージング テーブルをシードしました。これが私が始めたベースクエリです:
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
;
ここで、ベース クエリをループ処理して、挿入クエリを動的に作成します。私のショップでは DataStage を使用していますが、そのアプローチは難解であり、ここで説明する価値はありません。
注: ここでは、動的 SQL をループして構築するために少し作業が必要です。シェル、Perl、Python などの無数のフレーバーを使用できます。2 つの列キーを持つサンプル テーブルを使用して、ステージング テーブルに挿入するために作成するものを次に示します。
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};
すべてのテーブルをループしてステージング テーブルをシードした後、一連のクエリを実行し、データベース、所有者、テーブル名、および行 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
)
;
最後に、最新のレコードをターゲット テーブルに挿入します。
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'
)
;
注: 当方の環境では、挿入のみのモデルが必要なわけではありません。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}'
);
主キー宣言の違いに関係なく、シンプルですべてのテーブルで同じであるため、これが気に入っています。
また、このクエリを頻繁に使用して、現在の主キー違反をテーブルごとに表示します。
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;
それはすべてを要約します。一部の人々がそれを便利だと思うことを願っています。私たちはすでにこのアプローチで多くの進歩を遂げています。この時点で、なぜ私がこのようなトラブルを起こしたのか疑問に思われるかもしれません。私は PK 違反が私たちの倉庫に持ち込まれることを嫌悪しており、それらを根絶するための包括的なアプローチを望んでいました. 上記のプロセスは、数か月間、本番環境で毎日実行されています。主キーが宣言された最大 350 個のテーブルがあり、サイズは 5 行ディメンションから最大 2 億行ファクト @ 10Gb までの範囲です。Netezza にとって、これはかなり控えめな出費です。Mustang NPS 10050 では、プロセス全体に 10 分もかかりません。