web-dev-qa-db-ja.com

クラスター化インデックスとパーティション列の違い

パーティショニングを理解しているように、パーティショニングする列は、物事がパーティションに分割される方法です。

しかし、パーティション列はディスク上の順序と関係がありますか? (データが入るパーティションは別です。)

次のようなテーブルがあるとします。

CREATE TABLE [dbo].[Something](
    [SomethingId] [bigint] IDENTITY(1,1) NOT NULL,
    [OtherThingId] [bigint] NOT NULL,
    [CreatedBy] [int] NOT NULL,
    [CreatedWhen] [datetime] NOT NULL,
    [CreatedWhere] [varchar](255) NOT NULL,
     CONSTRAINT [PK_Something] PRIMARY KEY CLUSTERED 
    (
        [SomethingId] DESC
        [OtherThingId] DESC,
    )
) ON OtherThingIdPartitionScheme(OtherThingId)

新しい行が格納されるパーティションは、OtherThingIdによって決定されます。

しかし、クラスター化インデックスを最初にSomethingId、次にOtherThingIdになるように設定しました。

各パーティションがSomethingId、次にOtherThingIdの順に並べられるということですか?
(OtherThingIdの2次値によってのみパーティション化されている場合でも)

(私は現在、多くのパーティションを設定しており、完全に理解していることを確認したいと思います。)

3
Vaccano

しかし、パーティション列はディスク上の順序と関係がありますか?

クラスター化インデックス構造から

クラスター化インデックスのsys.partitionsには1つの行があり、インデックスで使用されるパーティションごとにindex_id = 1があります。 デフォルトでは、クラスター化インデックスには単一のパーティションがあります。クラスタ化インデックスに複数のパーティションがある場合、各パーティションには、その特定のパーティションのデータを含むBツリー構造があります。たとえば、クラスタ化インデックスに4つのパーティションがある場合、4つのB-ツリー構造;各パーティションに1つ。

テーブルとインデックスの編成から:

テーブルまたはインデックスが複数のパーティションを使用する場合、データは水平方向にパーティション分割されるため、行のグループは指定された列に基づいて個々のパーティションにマップされます。パーティションは、データベース内の1つ以上のファイルグループに配置できます。 データに対してクエリまたは更新が実行されるとき、テーブルまたはインデックスは単一の論理エンティティとして扱われます。

データチェーン内のページとその中の行は、クラスター化インデックスキーの値に基づいて並べられます。すべての挿入は、キーの位置で行われます。挿入された行の値は、既存の行間の順序付けに適合します。 Bツリーのページコレクションは、sys.system_internals_allocation_unitsシステムビューのページポインターによって固定されます。

データのレイアウト方法について詳しく知りたい場合は、以下を参照してください。 ストレージエンジン内部:sp_AllocationMetadata

補足として:SQL Server 2016 CTP2には TRUNCATE TABLE ... [WITH(PARTITIONS({|}

パーティションの切り替えを自動化するためのチェックアウト- SQL Server Partition Management Utility

2
Kin Shah

Kin Shah答え に追加するには、次のクエリが役立ちます。

SELECT
 o.type_desc             AS  objtype,
 u.name                  AS [schema],
 o.name                  AS  object,
 i.type_desc             AS  idxtype,
 i.index_id              AS  idxid,
 ISNULL(i.name, '*Heap') AS [index],
 p.partition_number      AS  partitn,
 p.partition_id,
 p.rows,
 p.data_compression_desc AS  compr,
 a.allocation_unit_id    AS  alloc_unit_id,
 a.type_desc             AS  alloc_unit_type,
 8 * a.total_pages       AS  totl_KB,
 8 * a.used_pages        AS  used_KB,
 8 * CASE WHEN i.index_id < 2 THEN a.data_pages
     END                 AS  data_KB,
 CONVERT(varchar(6),  CONVERT(int, CONVERT(binary(2), REVERSE(SUBSTRING(a.first_page,     5, 2))))) + ':' +
 CONVERT(varchar(20), CONVERT(int, CONVERT(binary(4), REVERSE(SUBSTRING(a.first_page,     1, 4))))) AS first_page,
 CONVERT(varchar(6),  CONVERT(int, CONVERT(binary(2), REVERSE(SUBSTRING(a.root_page,      5, 2))))) + ':' +
 CONVERT(varchar(20), CONVERT(int, CONVERT(binary(4), REVERSE(SUBSTRING(a.root_page,      1, 4))))) AS root_page,
 CONVERT(varchar(6),  CONVERT(int, CONVERT(binary(2), REVERSE(SUBSTRING(a.first_iam_page, 5, 2))))) + ':' +
 CONVERT(varchar(20), CONVERT(int, CONVERT(binary(4), REVERSE(SUBSTRING(a.first_iam_page, 1, 4))))) AS first_iam_page
FROM       sys.objects AS o
LEFT  JOIN sys.schemas AS u
 ON  o.schema_id = u.schema_id
LEFT  JOIN sys.indexes AS i
 ON  o.object_id = i.object_id
INNER JOIN sys.partitions AS p
 ON  i.object_id = p.object_id
 AND i.index_id  = p.index_id
LEFT  JOIN sys.system_internals_allocation_units AS a  -- Internal variant of sys.allocation_units.
 ON p.partition_id = a.container_id
WHERE o.is_ms_shipped = 0
 AND  a.total_pages   > 0
ORDER BY o.type, u.name, o.name, i.index_id, p.partition_number
0