web-dev-qa-db-ja.com

大きなテーブルを分割してもパフォーマンスは向上しません。なぜですか?

SQL Server 2014では、大きなテーブルの1つを毎週パーティション分割し、スライディングウィンドウシナリオを定義して、最も古い週のデータをアーカイブDBに切り替え、次の週のために新しいパーティションを作成しました。

これが結果です:

enter image description here

これはAVLシステム(車両追跡)用です。 PositionDatedatetime)で分割しました。すべてのクエリのWHERE句にPositionDateがあり、多くの場合VehicleIdWHERE句でも。 VehicleIdint)に2つの整列インデックスを作成しました:

  • (PositionDate、VehicleId);
  • (VehicleId)

ただし、WHERE句にVehicleIdを含むすべてのクエリでは、これらの2つの非クラスター化インデックスはどちらも使用されません(クエリプランによると)。

現在、パフォーマンスに問題があります。

次のようなクエリについて、パーティションテーブルと非パーティションテーブルのクエリプランを比較しました。

Select * from MyNonPart_Table Where PositionDate between '2016-05-01' AND '2016-06-01'

Select * from PartitinedTable Where PositionDate between '2016-05-01' AND '2016-06-01'

最初のクエリのコストは30%ですが、2番目のクエリは70%です。

パーティションテーブル用に2つのファイルを含む1つのファイルグループがあります。

私の質問:

  1. 各パーティションの行数は、パーティション化に最適な行数よりも多いですか?日ごとにパーティション分割し、過去60日間のデータをライブで保持している場合、パフォーマンスの向上に役立ちますか?

  2. 非クラスター化インデックスは明確に定義されていますか、それとも削除する必要がありますか?すべてのクエリのWHERE句にPositionDateがあり、多くのクエリにはVehicleIdがあります。そのうちの。

  3. このシナリオでパーティショニングを誤用していますか?パーティション分割されていないテーブルに適切なインデックスを定義し、最も古いデータ(2か月以上前)をアーカイブテーブルに移動すると、私の場合はうまくいきますか?

私のインデックスのDDL:

ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [PK_Primary] PRIMARY KEY CLUSTERED 
(
    [PositionDate] ASC,
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

CREATE NONCLUSTERED INDEX [NonClusteredIndex-VehicleId] ON [dbo].[MyTable]
(
    [VehicleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

CREATE NONCLUSTERED INDEX [NCIX_VehicleId_PositionDate] ON [dbo].[MyTable]
(
    [VehicleId] ASC,
    [PositionDate] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

これは例です。私のクエリはdatetime型のパラメーターを受け取るSPにあります。

4
Javad

通常、妄想に従いました。そのパーティション分割により、標準インデックスと比較して、クエリのパフォーマンスが大幅に向上します。

これはそうではありません。インデックスによるフィルタリングとパーティションによるフィルタリングの違いはほとんどありません。

パーティションは、クエリを高速化するためではありませんが、高速なDELETEを可能にするために-空のバージョンのテーブルでパーティションをスワップアウトすることによって。これにより、テーブルの一部を削除するための「切り捨て」スタイルのパフォーマンスが可能になります。これは重要です。非常に重要なことですが、長い時間を経験した場合、数十ギガバイトのデータを削除するのに時間がかかることがあります。

パーティションが役立つ挿入シナリオもあります。

しかし、クエリの場合-いいえ、パーティションは適切なインデックスよりも優れたものにはなりません。実際、作業はより複雑になるため(アクセスするパーティションの管理)、速度は遅くなります。

15
TomTom

TomTomには 素晴らしい答え があり、これに完全に同意します。 sp_BlitzErikは、パーティション分割はパフォーマンス機能ではないことを認める良い情報源として、ケンドラリトルを正しく引用しています。

テーブルのパーティション分割によってクエリのパフォーマンスが向上しない理由

実際、パーティショニングはデータ管理機能です。 TomTomによって指摘されているように、パーティション内のデータセットを含む一括DELETE操作は、単純なメタデータスイッチを使用してマイクロ秒単位で実行されます。さらに、「コールド」データを低速のストレージにロールオフし、高速ストレージを「ホット」データ用に解放できるようにするファイルとファイルグループを使用していくつかのことを実行できます。

パーティショニングがパフォーマンス機能であると考える人がいますときどきパーティションが削除され、スキャンされるデータの量が1つに減ります。またはいくつかのパーティション。ただし、パーティションを削除するには、条件が適切であり、制御されたクエリ開発環境が必要です。

たとえば、パーティション化されたデータベースは、複雑なクエリや暗黙的な変換でパーティションを削除するのに苦労しています。最後に、パーティションの削除が使用されていないパーティションテーブルでは、クエリは実際には、パーティション分割されていないクエリよりも遅くなる可能性があります。特に パーティションの数が増えるにつれて

パーティショニングは、大きなテーブルを単に投げるだけのものではなく、「より速く」機能することを願っています。パーティションキーからパーティションの粒度、保持戦略、ストレージ戦略まで、そのすべての側面にどのように取り組むかについて、慎重に考える必要があります。

最後に、コスト見積もりだけを使用しないでください。 SET STATISTICS TIME ON ...およびSET STATISTICS IO ONを使用してクエリを実行し、実際に何が行われているかを把握します。

9
swasheck