3

SQLクエリに最適なインデックスを作成したい. ユーザーは、クエリを作成する UI のオプションを選択できます。テーブルとクエリは次のとおりです。

CREATE TABLE [dbo].[MyTable](
    [Id] [nvarchar](32) NOT NULL,
    [SomeKey] [int] NOT NULL,
    [Col1] [nvarchar](max) NULL,
    [Col2] [nvarchar](max) NULL,
    [NumCol1] [int] NOT NULL,
    [NumCol2] [int] NOT NULL,
    [BitCol1] [bit] NOT NULL,
    [BitCol2] [bit] NOT NULL,
    [Created] [datetime] NOT NULL
CONSTRAINT [PK_dbo.MyTable] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

クエリはここにあります(SP):

ALTER PROCEDURE [dbo].[MyTable] 
@SomeKey INT,@Col1 BIT,@Col2 BIT,@BitCol1 BIT,@BitCol2 BIT,
@NumCol1 INT,@NumCol2 INT,@offset INT,@take INT
AS
DECLARE @sql NVARCHAR(MAX), @paramlist  nvarchar(4000) 
SET @sql = 'SELECT [Id],[SomeKey],[Col1],[Col2],[NumCol1],[NumCol2],[BitCol1],[BitCol2], FROM MyTable WHERE SomeKey = @SomeKey'
IF @NumCol1 IS NOT NULL SELECT @sql = @sql + ' AND NumCol1 = @NumCol1'
IF @NumCol2 IS NOT NULL SELECT @sql = @sql + ' AND (NumCol2 > @NumCol2)'
IF @Col1 IS NOT NULL SELECT @sql = @sql + ' AND (Col1 = '''' OR Col1 IS NULL)'
IF @Col2 IS NOT NULL SELECT @sql = @sql + ' AND (Col2 = '''' OR Col2 IS NULL)'
IF @BitCol1 IS NOT NULL SELECT @sql = @sql + ' AND BitCol1 = 1'
IF @BitCol2 IS NOT NULL SELECT @sql = @sql + ' AND BitCol2 = 1'
SELECT @sql = @sql + ' ORDER BY Created OFFSET @offset ROWS FETCH NEXT @take ROWS ONLY'
SELECT @paramlist = '@SomeKey INT, @Col1 INT, ....'
EXEC sp_executesql @sql, @paramlist, @SomeKey, @Col1, @Col2, ...

あなたが要点を理解することを願っています。私はdbにクエリ文字列を作成して実行しています。param Col1 = true を送信すると、db からすべての空の Col1 が必要になります。アプリから、すべてのパラメーターを準備していることを確認します。残りは自明だと思います(ただし、コメントで質問をしてください)!

インデックススキャンや同様の「遅い」検索を回避するために、このテーブル/クエリのインデックスを作成する方法は? そして、私はただの Web 開発者なので、この (高度な) インデックス作成は私にとって新しいものです! Db は SQL Server 2012 です。

更新: 使用シナリオ
テーブルには最大 100k から 10m-20m の行があります。行は更新されません。アプリの実行中 (常に実行されているわけではありません)、5 ~ 10 分以上ごとに 500 (sqlbulkcopy c# クラス) の一括挿入が行われます。週に 1 回、いくつかの行が削除されます (SomeKey 列に基づく)。
アプリには多くのユーザーがいないため (おそらく同時に少数、最大で 10 人)、1 秒あたりのクエリ数は多くありません (5 ~ 10 秒ごとに 1 つのクエリですか?)。 、秒ではありません)。

4

2 に答える 2

1

インデックスはトレードオフです。テーブル内のデータ変更時に更新する必要があるため、INSERT と UPDATE が多いテーブルには注意してください。

SQL Server Management Studio では、クエリの実行プレイを確認できます。そのためのオプションが Query メニューの下にあります。クエリの実行中に最も時間がかかるものを確認できます。

その他のオプションは、メニューの [ツール] > [データベース エンジン チューニング アドバイザー] からアクセスできるチューニング アドバイザーです。作成するインデックスを提案します。

WHERE などの検索で使用する変数は、インデックスを作成するのに適した候補です。

インデックスはあなたを殺すものではありません。それをいじって最適な解決策を見つけることができ、本番中に大きな問題なく変更を加えることができます。残念ながら、インデックスが必要かどうかの決定は、テーブルの設計だけでなく、このテーブルのデータ量、データの多様性、およびテーブルで実行する操作の性質にも基づいています。

アップデート:

あなたに役立つもの:

MSDN クエリのパフォーマンス

MSDN クエリのチューニング

あなたの実行計画を参照して、入れ子になったループの結合についての部分を読むことをお勧めします

通常、インデックス スキャンは、特定の列から大きな割合のデータを取得した結果です。

于 2013-02-07T13:37:09.640 に答える
0

最適なソリューションは、扱うリソースによって異なります。テーブルが保持する行数、使用可能なメモリ/スペースの量、動的パラメーターが使用される頻度、テーブルの一般的な使用パターン (より多くの読み取り)書き込みよりも?)。

まず最初に、常に参照されるインデックスを追加してから、順序付けも常に使用されるためSomeKey、追加を試してみます。Created列のフィルタリングを静的にすることでロジックを改善することもできbitます (それらは常に一方向または他方向です - すべての可能な値を知っています) と の間のインデックスに追加しSomeKeyますCreated

最後にINT、キーの含まれる列として列を追加して、追加されたインデックス サイズが少ないディスク読み取りで相殺されるかどうかを確認することができます。

すべてが一般的なワークロードに依存するため、これは初心者向けです。それに応じてテストを行います。

于 2013-02-07T13:53:53.300 に答える