2017-08-05 8 views
4

IOTメトリック(timeseriesデータ)用のClustered Columnstore Index Tableがあります。これには10億行以上が含まれており、次のような構造になっています。2008年までのデバイスID値とタイムスタンプの範囲は、10,000個におよぶ10,000個の異なるDeviceId値とタイムスタンプがあります。このテーブルに対する典型的なクエリは次のようになります。SQL Server Columnstore Alignmentを最適化する方法

SET STATISTICS TIME, IO ON 
SELECT 
    [DeviceId] 
    ,[MetricId] 
    ,DATEADD(hh, DATEDIFF(day, '2005-01-01', [TimeStamp]), '2005-01-01') As [Date] 
    ,MIN([Value]) as [Min] 
    ,MAX([Value]) as [Max] 
    ,AVG([Value]) as [Avg] 
    ,SUM([Value]) as [Sum] 
    ,COUNT([Value]) as [Count] 
FROM 
    [dbo].[Data] 
WHERE 
    [DeviceId] = 6077129891325167032 
    AND [MetricId] = 1000 
    AND [TimeStamp] BETWEEN '2017-07-01' AND '2017-07-30' 
GROUP BY 
    [DeviceId] 
    ,[MetricId] 
    ,DATEDIFF(day, '2005-01-01', [TimeStamp]) 
ORDER BY 
    [DeviceId] 
    ,[MetricId] 
    ,DATEDIFF(day, '2005-01-01', [TimeStamp]) 

私はこのクエリを実行すると、私はパフォーマンスメトリックのためにこれを取得する:

ため、現時点では上記のようなクエリはありませんあまりにも多くのセグメントが、私は信じて読み込みます:

Table 'Data'. Scan count 2, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 5257, lob physical reads 9, lob read-ahead reads 4000. 
Table 'Data'. Segment reads 11, segment skipped 764. 

クエリプラン: Query plan

これはよく、私はそこのようにwを信じて最適化されていません(グループ化/集計の前に)

それではNiko Neugebauerの素晴らしいスクリプトを実行して、セットアップとColumnstore Alignment https://github.com/NikoNeugebauer/CISL/blob/master/Azure/alignment.sqlを検証したところ、Columnstoreを再構築した後にこの結果が得られましたクラスタ化インデックス:

Columnstore Alignment

METRICIDとタイムスタンプ列は、100%の最適なアラインメントスコアを持っています。 DeviceId列もうまく整列されるようにするにはどうすればよいですか?私は最初のClustered(Rowstore)インデックスで列の順序で演奏しました。

+0

XMLとしてクエリプランを貼り付けてくださいだけでなく、あなたは、SQL Server 2016を使用している場合は、使用しようと – TheGameiswar

+0

dbcc clonedbとdbを共有して、他の人があなたが直面している正確なシナリオを再現できるようにします.2016を使用していない場合は、テーブルスキーマ、インデックス、統計をスクリプト化してスクリプトを共有できます – TheGameiswar

+1

@TheGameiswar [DBCC CLONEDATABASE](https ://support.microsoft.com/en-gb/help/3177838/how-to-use-dbcc-clonedatabase-to-generate-a-schema-and-statistics-only)は、SQL Server 2014 SP2以降で使用できます。 ) – wBob

答えて

5

DeviceIdでテーブルを整列させるための重要なソリューションは、テーブルにクラスタ化された行ストアインデックスを作成し、その上にMAXDOP = 1のクラスタ化Columnstoreインデックスを作成することです(インデックス構築時に重複が発生しないように複数のコアで動作します)。 だから可能なコードは次のようになります。

CREATE CLUSTERED INDEX [PK_Data] ON [dbo].[Data] ([DeviceId],[TimeStamp],[MetricId]) --WITH (DROP_EXISTING = ON) 
CREATE CLUSTERED COLUMNSTORE INDEX [PK_Data] ON [dbo].[Data] WITH (DROP_EXISTING = ON, MAXDOP = 1, DATA_COMPRESSION = COLUMNSTORE_ARCHIVE) 

別の可能性は、アライメントfuncitonalityを準備してから実行することで、CISL内ですべてを行うには、次のようになります。

insert into dbo.cstore_Clustering(TableName, Partition, ColumnName) 
    VALUES ('[dbo].[Data]', 1, 'DeviceId'); 

これはただのためにかかわらず、です1パーティションを使用していますが、使用している番号に入ると、テーブルのパーティション分割を検討する必要があります。 セットアップが完了したら、dbo.cstore_doAlignmentの実行を開始することができます。これにより、自動的にテーブルの再配置と最適化が行われます。

敬具、 ニコを(あなたが好きな場合は、最適化のしきい値を設定するには、いくつかのパラメータを持つことになります)

+0

ありがとう@Niko。私はあなたの答えを正確に理解していますか?私たちはIOTメトリックのためにテーブルをタイムスタンプ列(月ごと?)で区切り、このテーブルをDeviceIdで整列させるべきです。 我々の集計では、常に1つのDeviceId、可能な複数の異なるMetricId、1か月か12か月の範囲のタイムスタンプ(時間と日ごとのグループ化)を照会します。 –

+0

Ted、 (私の認識が変わるかもしれませんが)、TimeStampでパーティション化し、DeviceIdで整列するのは良いオプションのようです。 よろしくお願いいたします。 Niko –

+0

ありがとう、@ニコ! TimeStampに月単位でパーティション化を実装し、DeviceIdで整合させました。結果は有望ですが、ほとんどのクエリ(75%)は< 100msで実行されますが、25%は2,000msかかるため、検証が必要です。間にあまりないそれはすべて、Premium Azure SQL弾性プール上で実行されます。これは3秒ごとに1回実行される同じクエリであるため、スロットルマージンは適用されません。 セクション行のボリュームを分割するための提案は何ですか?今月選択しますが、多すぎるパーティション数につながる可能性があります。 –

関連する問題