web-dev-qa-db-ja.com

クラスター化されたインデックス(主キーが宣言されたときに作成される)に対する列ストアインデックス-SQL Server

クラスタ化インデックスが作成されると、テーブル自体がインデックスキーでソートされたインデックス構造になります。

テーブルXPTOに5つの列(a、b、c、d、e)があり、 "a"が主キーであり、列(b、c)を持つテーブルXPTOに列ストアインデックスを作成するとします。

このインデックスの構造は何ですか?クラスタ化されたテーブルとは異なる構造ですか?または、列ストアに(他の非クラスター化インデックスのように)クラスター化されたテーブルへのポインターがありますか?.

最後に、同じシナリオですが、すべての属性を持つ列インデックスを作成します。構造は何ですか。

5
Silva_PT_SCP

テストスクリプトを作成することで、多くのことを学ぶことができます。以下のSQLを任意のSQL 2014インスタンスで実行できるはずです(おそらくSQL 2012も同様ですが、ここではテストしていません)。

このスクリプトから、(b、c)の非クラスター化列ストアインデックスはクラスター化インデックス列(a)のデータを格納し、bとcを格納するのと同じ方法で(セグメントを介して)格納することがわかります。これにより、a、b、cにアクセスするクエリをcolumstoreで効率的に処理できます。技術的には、テーブル内のすべての列を必要とするクエリを処理するために、キールックアップと組み合わせて列ストアを使用することもできます(ただし、これは、キー検索)。

列ストアインデックスの「構造」についての質問に関しては、ここでは答えるには深すぎる質問だと思います。しかし、もっと詳しく知りたい場合は、Niko Neugebauerのコラムストアに関する55部(および成長中)の優れたシリーズに、構造と内部構造に関する貴重な情報がたくさんあると思います。 http://www.nikoport.com/columnstore /

-- Create a table to your specs
CREATE TABLE dbo.XPTO (a BIGINT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT NOT NULL, e INT NOT NULL, CONSTRAINT PK_XPTO PRIMARY KEY (a))
GO

-- Insert some trivial dummy data
INSERT INTO dbo.XPTO (a, b, c, d, e)
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)), v2.x, v3.x, v4.x, v5.x
FROM ( VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10) ) v(x)
CROSS JOIN ( VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10) ) v2(x)
CROSS JOIN ( VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10) ) v3(x)
CROSS JOIN ( VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10) ) v4(x)
CROSS JOIN ( VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10) ) v5(x)
CROSS JOIN ( VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10) ) v6(x)
GO

-- Create the nonclustered columnstore
CREATE NONCLUSTERED COLUMNSTORE INDEX cs_XPTO ON dbo.XPTO (b, c)
GO

-- Turn on "Include Actual Execution Plan"

-- Access only the columns specified in the columnstore index
-- Here we get a Columnstore Index Scan, as expected
SELECT SUM(b), SUM(c)
FROM XPTO
GO

-- Add in the clustered index column
-- Now we also get a Columnstore Index Scan!
-- This shows that the non-clustered columnstore does maintain data for "a"
-- because it is able to process this query without touching the clustered index
SELECT SUM(a), SUM(b), SUM(c)
FROM XPTO
GO

-- Access all columns
-- Now we get a Clustered Index Scan, and the columnstore index is not used
SELECT SUM(a), SUM(b), SUM(c), SUM(d), SUM(e)
FROM XPTO
GO

-- Try to force usage of columnstore
-- Now we see a tplan that uses the columnstore index but performs a key looked up to the clustered index
-- This is a plan shape I have never seen the query optmizer generate on its own, but it makes sense
-- that it is possible given that the columnstore index stores data for the clustered index column,
-- which is essentially a pointer to the corresponding row in the table
SELECT SUM(a), SUM(b), SUM(c), SUM(d), SUM(e)
FROM XPTO WITH(INDEX(cs_XPTO))
GO

-- View the column store segments
-- Here we see that there is a column store segment for columns a, b, and c (even though we asked for just b and c!)
-- This seems to indicate that clustered index columns are implicitly added to any nonclustered columnstore index
-- and are stored within that columnstore index in the same way as the requested columns
SELECT cs.*
FROM sys.partitions p
JOIN sys.column_store_segments cs
    ON cs.partition_id = p.partition_id
WHERE p.object_id = OBJECT_ID('XPTO')
GO

-- Cleanup
DROP TABLE dbo.XPTO
GO
4
Geoff Patterson