0

大きなコントラクトテーブルがあり、ステータスがOpenのコントラクトをクエリする多くのストアドプロシージャがあります。契約の10%未満がオープンであり、この数はDBが大きくなるにつれて減少しています。クエリの一部を高速化するために、オープンコントラクトのインデックス付きビューを作成できると思いました。問題は、ステータスがコントラクトテーブルになく、必要なデータを取得するためにサブクエリが必要なことです。(SQL Serverは、私が調べたクエリでテーブル全体に対してクラスター化インデックススキャンを実行します)

これがビューの要約バージョンです(コントラクトテーブルから他の30列を削除しました)

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE VIEW [dbo].[vw_OpenContractsIndexed]
WITH SCHEMABINDING 
AS
SELECT     c.ContractID
FROM         dbo.NMPT_Contract AS c INNER JOIN
                      dbo.NMPT_ContractStatus AS cs ON c.ContractID = cs.ContractID AND cs.ContractStatusCreated =
                          (SELECT     MAX(ContractStatusCreated) AS Expr1
                            FROM          dbo.NMPT_ContractStatus AS cs2
                            WHERE      (ContractID = c.ContractID)) INNER JOIN
                      dbo.CMSS_Status AS s ON cs.StatusID = s.StatusID
WHERE     (s.StatusCode = 'OPN')

ビューにインデックスを作成しようとすると(で一意にクラスター化されますcontractid)、次のようになります

インデックスの作成に失敗しました
1つ以上の許可されていない構成が含まれています。(Microsoft SQL Server、エラー1936)

私が収集できるものから、問題はサブクエリの最大値ですか?

ステータスを契約テーブル(私が個人的に属すると思う場所)に置く以外に、この状況を最適化するための提案があります。これに失敗すると、他のバージョンのSQL Serverでこのインデックス付きビューが許可されますか?

4

3 に答える 3

3

SS 2000 のインデックス付きビューに関する TechNet から:

ビュー定義の構文にはいくつかの制限があります。ビュー定義には、次を含めることはできません。

カウント(*)

ROWSET 関数

派生テーブル

自己結合

明確

STDEV、VARIANCE、AVG

Float*、text、ntext、image 列

サブクエリ

全文述語 (CONTAIN、FREETEXT)

null 許容式の SUM

最小、最大

外部結合

連合

とサブクエリを使用していますがMAX、どちらも許可されていません。

これを回避する方法についてアドバイスを得るには、いくつかのデータと何をしようとしているのかを共有する必要があります。

于 2012-07-12T16:12:46.747 に答える
1

これは「ビュー」ソリューションではなく、達成するにはさらに多くの作業が必要になりますが、ビューの結果を保持する非正規化テーブルを作成できます。このように、Open コントラクトのすべての読み取りは、そのテーブルに対して行うことができます。これは最速ですが、新しいテーブルのメンテナンスが必要になります。

于 2012-07-12T16:27:39.453 に答える
0

インデックス付きビューの作成は、非常に多くの制限があり、1つは自己結合にも関連しているため、静かな困難な作業です。ここに自己参加します。他のビューなどはありません。

'OPEN'のような単一のステータスのみを使用している場合のこれらの種類のマスターテーブルの他のことは、テーブル(ステータスコードを持つマスターテーブル)を結合する代わりに、statusid変数を宣言してからステータスの値を格納することをお勧めしますそこで開き、最終的なクエリでその値を使用します。これにより、マスターテーブルとの余分な結合が回避されます。

最終ステートメントでコントラクトテーブルと結合する前に、オープンステータスのデータを一時テーブルに保存することをお勧めします。statusid、customerid、contractcreationdateのインデックスを作成できます。次に、このインデックスを強制して、contractIdを次のような一時テーブルに入れます。

 select contractid into #temp from NMPT_ContractStatus 
where statusid =@statusid group by contractid          
having     datefield = max(datefield)

次に、この一時テーブルを契約テーブルと結合します。

ただし、あらゆる種類のインデックスを作成する前に、これらのオーバーヘッドが、得られるメリットよりもはるかに少ないことを確認してください。

于 2012-07-14T12:15:30.257 に答える