1

いくつかのスパース列を含むテーブルとスパース列を含まないテーブルを比較するテストを実行しましたが、スペースがまったく節約されていません。

2 つのテーブルがあり、どちらも主に varchar 列にアドレス情報を格納しています。どちらのテーブルも null を許可し、一方のテーブルには列の疎なプロパティ セットがあります。

それぞれに 1000 行のデフォルト値を挿入します (デフォルト値は null です)。スパース列は null を別の方法で格納するため、スペースを節約できると思います。しかし、sp_spaceUsed を実行すると、節約が見られません。私が間違っていること、または私の理解が間違っている場所についてのアイデアはありますか?

    Create Table SparseColTest_NonSparse
    (
        AddressID int identity(1,1) not null,
        AddressLine1 varchar(500)  null,
        AddressLine2 varchar(500)  null,
        AddressLine3 varchar(500)  null,
        PostalCode varchar(20)  null,
        Country varchar(50) 
    )

    Create Table SparseColTest_Sparse
    (
        AddressID int identity(1,1) not null,
        AddressLine1 varchar(500) sparse null,
        AddressLine2 varchar(500)  sparse null,
        AddressLine3 varchar(500)  sparse null,
        PostalCode varchar(20)  sparse null,
        Country varchar(50) 
    )


    declare @i int
    set @i = 0

    while(@i <= 100000)
    BEGIN

        insert into SparseColTest_NonSparse Default values
        insert into SparseColTest_Sparse default values

        set @i = @i + 1
    END

    exec sp_spaceUsed 'SparseColTest_NonSparse'
    exec sp_spaceUsed 'SparseColTest_Sparse'

    /*
    name                          rows                 reserved           data                       index_size         unused
    ----------------------------- -------------------- ------------------ -------------        ----- ------------------ ------------------
    SparseColTest_NonSparse       210003               2888 KB            2840 KB                    8 KB               40 KB


    name                          rows                 reserved           data                       index_size         unused
    ----------------------------- -------------------- ------------------ -------------        ----- ------------------ ------------------
    SparseColTest_Sparse                210003               2888 KB            2840 KB                    8 KB               40 KB

    ****NOTE - even with 210k rows sparse and non sparse tables are identical in size.
    */
4

1 に答える 1

3

問題は、ページ上のストレージです。これは、何が起こるかの概算です。

スペースは、次の理由で使用されます。

  1. アドレス ID (4 バイト)
  2. NULL ビット マップ (両方のテーブルで 1 バイト)
  3. スパース列のリスト (NULL フィールドごとに 2 バイト)
  4. 列の値のリスト (NULL varchar はスペースを取らないため、何もありません)
  5. スパース列の 6 バイトのオーバーヘッド (参照のみがここにあります)
  6. その他の小さなオーバーヘッド

これには説明が必要かもしれません。両方のテーブルに があるAddressIDため、同じ量のスペースを占有します。

すべての非スパース列は NULL ビットマップにあります。NULL可能なものだけがそこにあると思うかもしれませんが、違います。SQL Server には、それらすべてのビットマップがあります。一度に 1 バイトずつ格納されます。したがって、非スパース テーブルの 6 つの列は、スパース テーブルの 2 つの非スパース列 (ID と国) と同じスペースを使用します。

Varchar は可変長データです。NULL の場合でも、列ごとに 2 バイトが予約されます。したがって、これは最初のレコードで 10 バイトです。2 番目の 2 バイト。

スパース レコードには 6 バイトのオーバーヘッドがあります。

スパース列は、値がある場合にのみスペースを占有します。ここには値がありません。

最終的な結果は、オーバーヘッドと、場合によってはバイト アラインメントの制限を合計すると、両方のレコードで同じ長さになります。非疎テーブルの対応する列の値は、長さのためにいくらかのスペースを占めています。これは、列によって使用されるスペースと一致しているようです。また、ページ上のデータ行が 2 バイトまたは 4 バイトの境界で整列されていると思われます。NULL ビットマップは、両方のテーブルで同じサイズです。

非疎テーブルよりも疎テーブルに 8 つ以上の疎列があると、領域が節約されます。これにより、最も近いバイトに切り上げられる NULL ビット マップを確実に節約できます。

スパース列の実際の節約は、固定長データ型にあります。各値を格納するためのオーバーヘッドが増えますが、そこがまばらさの出番です。多くの値はありません。ビットマスク値が占有するスペースの両方のオーバーヘッドが失われます。

あなたの例では、スパース列は役に立ちません。実際のデータを使用すると、実際にストレージ スペースが増える可能性があります。

こちらのドキュメントをご覧ください。

于 2013-03-03T17:31:25.947 に答える