1

ここでは、SQL ServerManagementStudioで非クラスター化インデックスを調査しています。

100万を超えるレコードを含むテーブルを作成しました。このテーブルには主キーがあります。

CREATE TABLE [dbo].[Customers](
    [CustomerId] [int] IDENTITY(1,1) NOT NULL,
    [CustomerName] [varchar](100) NOT NULL,
    [Deleted] [bit] NOT NULL,
    [Active] [bit] NOT NULL,
 CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED 
(
    [CustomerId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,     ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

これは、実行プランが何を示しているかを確認するために使用するクエリです。

SELECT CustomerName FROM Customers

さて、追加の非クラスター化インデックスなしでこのコマンドを実行すると、実行プランに次のように表示されます。

I/O cost = 3.45646
Operator cost = 4.57715

現在、パフォーマンスを改善できるかどうかを確認しようとしているので、このテーブルの非クラスター化インデックスを作成しました。

1)最初の非クラスター化インデックス

CREATE NONCLUSTERED INDEX [IX_CustomerID_CustomerName] ON [dbo].[Customers] 
(
    [CustomerId] ASC,
    [CustomerName] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON,
ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

select Against Customersテーブルを再度実行すると、実行プランに次のように表示されます。

I/O cost = 2.79942
Operator cost = 3.92001

良さそうです。新しいインデックスを作成するために、作成したばかりの非クラスター化インデックスを削除しました。

2)最初の非クラスター化インデックス

CREATE NONCLUSTERED INDEX [IX_CustomerIDIncludeCustomerName] ON [dbo].[Customers] 
(
    [CustomerId] ASC
)
INCLUDE ( [CustomerName]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF,  
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF,   
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

この新しい非クラスター化インデックスを使用して、selectステートメントを再度実行すると、実行プランに同じ結果が表示されます。

I/O cost = 2.79942
Operator cost = 3.92001

では、どの非クラスター化インデックスを使用する必要がありますか?I / OとOperatorの実行プランでコストが同じなのはなぜですか?私は何か間違ったことをしていますか、それともこれは予想されますか?

ありがとうございました

4

3 に答える 3

2

これは、"CustomerName" がINCLUDE2 番目のインデックスで -ed されているためです ( INLCUDEd 列についてはこちらを参照してください)。

基本的に、両方のインデックスがまったく同じように機能します。最初のインデックス列が WHERE 句と一致しないカバーされたインデックスです。

どちらの場合も、クエリはインデックスをスキャンしますが、テーブルには触れません。

その特定のクエリのパフォーマンスが向上すると予想されるインデックスは、CustomerName だけのインデックスです。

于 2010-05-23T01:06:12.240 に答える
1

WHERE を使用して結果をフィルタリングするか、ORDER を使用して結果を並べ替えるか、またはインデックス付きの列の別のテーブルに結果を結合することによってインデックスを利用するまで、インデックスの有無に大きな違いはありません。

インデックスなしで次のようなクエリを実行してみてください。

SELECT *
FROM Customers
WHERE CustomerName = 'Marcus Adams'

次に、CustomerName 列にインデックスを追加して、再試行してください。

また、データベース システムが実際にインデックスを使用するのに十分な数の行がテーブルに必要であり、行のスキャンとインデックスの使用の違いに気付くのに十分な行が必要です。

于 2010-05-23T02:01:17.170 に答える
0

2つの非クラスター化インデックスのどちらも、実際にはあまり意味がありません。

重要なのは、クラスター化されたインデックスの列(この場合は)は、クラスター化されCustomerIdていないすべてのインデックスのすべてのエントリにすでに含まれているということです。結局のところ、そのクラスタリング列は、エントリが見つかった場合に実際のデータルックアップに使用されるものです。したがって、それを非クラスター化インデックスに追加することは、通常、不要であり、スペースの浪費にすぎません。

問題はもっとあります:表示したい行をどのように選択しますか?WHERE条項にはどの列が表示されますか?

ここでパターンを見つけた場合(たとえば、常にegで選択した場合City)、ニーズに合った非クラスター化インデックスは次のようになります。

CREATE NONCLUSTERED INDEX [IX_Customer_City] ON [dbo].[Customers] 
(
    [City] ASC
)
INCLUDE ( [CustomerName]) 

このようにして、SQL Serverに、特定の都市に一致する行を簡単に検索するメソッドを提供します。また、返したい列(CustomerName)を含めると、SQL Serverはインデックスページから直接必要な情報を取得できます(これにより、と呼ばれるcovering index-クエリをカバーします。たとえば、必要なすべての情報を返します)-「ブックマークルックアップ」を行う必要はありません。たとえば、実際のデータページからデータ行全体をフェッチしますCustomerCustomerIdクラスター化されたインデックスも、クラスター化キーであるため)。

于 2010-05-23T07:59:35.930 に答える