IDENTITY を使用して、Azure Synapse Analytics の専用 SQL プールで代理キーを作成する
この記事では、IDENTITY プロパティを使用して専用 SQL プール内のテーブルに代理キーを作成する場合の推奨事項と例を紹介します。
代理キーとは
テーブルの代理キーは、各行の一意の識別子を持つ列です。 代理キーはテーブル データからは生成されません。 データ モデラーは、データ ウェアハウス モデルを設計するときに、テーブルに代理キーを作成するのを好みます。 IDENTITY プロパティを使うと、この目的を簡単かつ効果的に達成でき、読み込みのパフォーマンスが影響を受けることもありません。
注意
Azure Synapse Analytics:
- IDENTITY 値は各ディストリビューションで自動的に増加し、他のディストリビューションの IDENTITY 値とは重複しません。 Synapse の IDENTITY 値は、ユーザーが明示的に "SET IDENTITY_INSERT ON" と重複する値を挿入するか IDENTITY を再シードする場合は、一意であるとは限りません。 詳細については、「CREATE TABLE (Transact-SQL) IDENTITY (プロパティ)」を参照してください。
- ディストリビューション列の UPDATE では、IDENTITY 値が一意であることは保証されません。 ディストリビューション列の UPDATE 後に DBCC CHECKIDENT (Transact-SQL) を使用して、一意性を確認します。
IDENTITY 列があるテーブルを作成する
IDENTITY プロパティは、読み込みパフォーマンスに影響を与えずに、専用 SQL プール内のすべてのディストリビューションにスケールアウトするように設計されています。 そのため、IDENTITY の実装はこれらの目標を達成するようになっています。
次のステートメントのような構文を使って、テーブルを最初に作成するときに、IDENTITY プロパティを持つようにテーブルを定義できます。
CREATE TABLE dbo.T1
( C1 INT IDENTITY(1,1) NOT NULL
, C2 INT NULL
)
WITH
( DISTRIBUTION = HASH(C2)
, CLUSTERED COLUMNSTORE INDEX
)
;
その後、INSERT..SELECT
を使ってテーブルを設定します。
以降、このセクションでは、理解を深めるのに役立つ実装の詳細に注目します。
値の割り当て
IDENTITY プロパティでは、データ ウェアハウスの分散アーキテクチャにより、サロゲート値が割り当てられる順序は保証されません。 IDENTITY プロパティは、読み込みパフォーマンスに影響を与えずに、専用 SQL プール内のすべてのディストリビューションにスケールアウトするように設計されています。
次にその例を示します。
CREATE TABLE dbo.T1
( C1 INT IDENTITY(1,1) NOT NULL
, C2 VARCHAR(30) NULL
)
WITH
( DISTRIBUTION = HASH(C2)
, CLUSTERED COLUMNSTORE INDEX
)
;
INSERT INTO dbo.T1
VALUES (NULL);
INSERT INTO dbo.T1
VALUES (NULL);
SELECT *
FROM dbo.T1;
DBCC PDW_SHOWSPACEUSED('dbo.T1');
この例では、2 つの行はディストリビューション 1 に格納されます。 1 番目の行の代理値は C1
列の 1 であり、2 番目の行の代理値は 61 です。 これらの値はどちらも IDENTITY プロパティによって生成されたものです。 ただし、値の割り当ては連続していません。 この動作は仕様です。
非対称のデータ
データ型の値の範囲は、ディストリビューション全体に均等に分散されます。 分散テーブルが非対称データによって悪影響を受ける場合、データ型に対して使用可能な値の範囲が早く不足する可能性があります。 たとえば、すべてのデータが最終的に 1 つのディストリビューションに格納される場合、実質的にテーブルはそのデータ型の値の 60 分の 1 にのみアクセスすることになります。 このため、IDENTITY プロパティは INT
および BIGINT
データ型だけに制限されます。
SELECT..INTO
既存の IDENTITY 列を選択して新しいテーブルにすると、次のいずれかの条件が満たされている場合を除き、新しい列は IDENTITY プロパティを継承します。
- SELECT ステートメントに結合が含まれています。
- 複数の SELECT ステートメントが UNION を使用して結合されている。
- IDENTITY 列が SELECT リストに複数回出現する。
- IDENTITY 列が式の一部である。
これらの条件が 1 つでも満たされている場合は、列に IDENTITY プロパティは継承されず、代わりに NOT NULL として作成されます。
CREATE TABLE AS SELECT
CREATE TABLE AS SELECT (CTAS) は、SELECT..INTO と同じ SQL Server 動作に従います。 ただし、ステートメントの CREATE TABLE
部分の列定義で IDENTITY プロパティを指定することはできません。 また、CTAS の SELECT
部分で IDENTITY 関数を使うこともできません。 テーブルに値を設定するには、CREATE TABLE
を使ってテーブルを定義した後、INSERT..SELECT
で値を設定する必要があります。
IDENTITY 列に値を明示的に挿入する
専用 SQL プールでは SET IDENTITY_INSERT <your table> ON|OFF
構文がサポートされています。 この構文を使って、IDENTITY 列に値を明示的に挿入できます。
多くのデータ モデラーは、ディメンションの特定の行に定義済みの負の値を使うことを好みます。 たとえば、-1 や "unknown member" 行です。
次のスクリプトでは、SET IDENTITY_INSERT を使ってこの行を明示的に追加する方法を示します。
SET IDENTITY_INSERT dbo.T1 ON;
INSERT INTO dbo.T1
( C1
, C2
)
VALUES (-1,'UNKNOWN')
;
SET IDENTITY_INSERT dbo.T1 OFF;
SELECT *
FROM dbo.T1
;
データの読み込み
IDENTITY プロパティが存在すると、データ読み込みコードに影響があります。 ここでは、IDENTITY を使ってテーブルにデータを読み込む場合のいくつかの基本的なパターンを示します。
IDENTITY を使ってテーブルにデータを読み込んで代理キーを生成するには、テーブルを作成した後、INSERT..SELECT または INSERT..VALUES を使って読み込みを実行します。
次の例では基本的なパターンを示します。
--CREATE TABLE with IDENTITY
CREATE TABLE dbo.T1
( C1 INT IDENTITY(1,1)
, C2 VARCHAR(30)
)
WITH
( DISTRIBUTION = HASH(C2)
, CLUSTERED COLUMNSTORE INDEX
)
;
--Use INSERT..SELECT to populate the table from an external table
INSERT INTO dbo.T1
(C2)
SELECT C2
FROM ext.T1
;
SELECT *
FROM dbo.T1
;
DBCC PDW_SHOWSPACEUSED('dbo.T1');
Note
現在は、IDENTITY 列のあるテーブルへのデータの読み込みに、CREATE TABLE AS SELECT
を使うことはできません。
データの読み込みの詳細については、専用 SQL プール向けの抽出、読み込み、変換 (ELT) の設計と読み込みのベスト プラクティスに関するページを参照してください。
システム ビュー
sys.identity_columns カタログ ビューを使用して、IDENTITY プロパティを持つ列を識別できます。
データベース スキーマを理解しやすいように、次の例では sys.identity_column を他のシステム カタログ ビューと統合する方法を示します。
SELECT sm.name
, tb.name
, co.name
, CASE WHEN ic.column_id IS NOT NULL
THEN 1
ELSE 0
END AS is_identity
FROM sys.schemas AS sm
JOIN sys.tables AS tb ON sm.schema_id = tb.schema_id
JOIN sys.columns AS co ON tb.object_id = co.object_id
LEFT JOIN sys.identity_columns AS ic ON co.object_id = ic.object_id
AND co.column_id = ic.column_id
WHERE sm.name = 'dbo'
AND tb.name = 'T1'
;
制限事項
次の場合、IDENTITY プロパティは使用できません。
- 列のデータ型が INT または BIGINT ではない場合
- 列が分散キーでもある場合
- テーブルが外部テーブルである場合
次の関連する関数は、専用 SQL プールではサポートされません。
一般的なタスク
このセクションでは、IDENTITY 列を操作するときの一般的なタスクを実行するために使うことができるいくつかのサンプル コードを提供します。
以下のすべてのタスクで、列 C1 が IDENTITY です。
テーブルに割り当てられた最も高い値を見つける
分散テーブルに割り当てられた最も高い値を特定するには、MAX()
関数を使います。
SELECT MAX(C1)
FROM dbo.T1
IDENTITY プロパティのシードと増分を調べる
カタログ ビューで次のクエリを使って、テーブルの ID 増分とシード構成値を調べることができます。
SELECT sm.name
, tb.name
, co.name
, ic.seed_value
, ic.increment_value
FROM sys.schemas AS sm
JOIN sys.tables AS tb ON sm.schema_id = tb.schema_id
JOIN sys.columns AS co ON tb.object_id = co.object_id
JOIN sys.identity_columns AS ic ON co.object_id = ic.object_id
AND co.column_id = ic.column_id
WHERE sm.name = 'dbo'
AND tb.name = 'T1'
;