2

このような質問があります。SELECT によって返されるデータの量 (つまり、文字数) が境界を超えるまで、私が期待するインデックスを使用する実行計画があります。その時点で、プランはインデックスを使用しなくなり、クエリは 100 倍以上遅くなります。

を使えばNVARCHAR(203)速いです。NVARCHAR(204)遅い。また、インデックスを使用しない場合は、CPU を完全に消費します。少なくともデータサイズの問題のように思えますが、洞察を探しています。

oldValueString と newValueString を NVARCHAR(255) に変更したところ、状況は少し良くなりましたが、プラン内のインデックスを失うことなくすべての列を照会することはまだできません。

SELECT
   [Lx_AuditColumn].[auditColumnPK],
   CONVERT(NVARCHAR(204), [Lx_AuditColumn].[newValueString])
FROM
   [dbo].[Lx_AuditColumn] [Lx_AuditColumn],
   [dbo].[Lx_AuditTable] [Lx_AuditTable]
WHERE
   [Lx_AuditColumn].[auditTableFK] = [Lx_AuditTable].[auditTablePK]
AND
   [Lx_AuditTable].[createdDate] >=  @P1
AND
   [Lx_AuditTable].[createdDate] <=  @P2
ORDER BY
   [Lx_AuditColumn].[auditColumnPK] DESC

これがテーブルの基本構造です (いくつかのインデックスと FK 制約を削除しました)。

CREATE TABLE [dbo].[Lx_AuditTable]
(
   [auditTablePK] [int] NOT NULL IDENTITY(1, 1) ,
   [firmFK] [int] NOT NULL ,
   [auditMasterFK] [int] NOT NULL ,
   [codeSQLTableFK] [int] NOT NULL ,
   [objectFK] [int] NOT NULL ,
   [projectEntityID] [int] NULL ,
   [createdByFK] [int] NOT NULL ,
   [createdDate] [datetime] NOT NULL ,
   CONSTRAINT [Lx_PK_AuditTable_auditTablePK] PRIMARY KEY CLUSTERED
   (
      [auditTablePK]
   ) WITH FILLFACTOR = 90
)
GO

CREATE INDEX [Lx_IX_AuditTable_createdDatefirmFK]
   ON [dbo].[Lx_AuditTable]([createdDate], [firmFK])
   INCLUDE ([auditTablePK], [auditMasterFK])
   WITH (FILLFACTOR = 90, ONLINE = OFF)
GO

CREATE TABLE [dbo].[Lx_AuditColumn]
(
   [auditColumnPK] [int] NOT NULL IDENTITY(1, 1) ,
   [firmFK] [int] NOT NULL ,
   [auditTableFK] [int] NOT NULL ,
   [accessorName] [nvarchar] (100) NOT NULL ,
   [dataType] [nvarchar] (20) NOT NULL ,
   [oldValueNumber] [int] NULL ,
   [oldValueString] [nvarchar] (4000) NULL ,
   [newValueNumber] [int] NULL ,
   [newValueString] [nvarchar] (4000) NULL ,
   [newValueText] [ntext] NULL ,
   CONSTRAINT [Lx_PK_AuditColumn_auditColumnPK] PRIMARY KEY CLUSTERED
   (
      [auditColumnPK]
   ) WITH FILLFACTOR = 90 ,
   CONSTRAINT [Lx_FK_AuditColumn_auditTableFK] FOREIGN KEY
   (
      [auditTableFK]
   ) REFERENCES [dbo].[Lx_AuditTable] (
      [auditTablePK]
   )
)
GO

CREATE INDEX [Lx_IX_AuditColumn_auditTableFK]
   ON [dbo].[Lx_AuditColumn]([auditTableFK])
   WITH (FILLFACTOR = 90, ONLINE = OFF)
GO

良い:

ここに画像の説明を入力

悪い:

ここに画像の説明を入力

4

3 に答える 3

1

このセットアップでは、(まだ) テーブル構造を詳細に知らなくても、次のことを行う必要があります。

  • テーブルに適切なクラスター化インデックスがあるdbo.Lx_AuditColumn (a のようなものINT IDENTITYはほぼ完璧です)
  • Lx_AuditColumn.auditTableFKJOIN と参照整合性チェックを高速化するための非クラスター化インデックス
  • 非クラスター化インデックスLx_AuditColumn.AuditColumnPK(もちろん、既にクラスター化された PK でない限り!)
  • 上の非クラスター化インデックスLx_AuditTable.CreatedDate

また、適切な ANSI/ISO 標準INNER JOIN構文を使用する必要があります (選択するテーブルのカンマ区切りのリストを使用するだけではなく、このトピックの背景情報については、 「キックする悪い習慣: 古いスタイルの JOIN を使用する」を参照してください) - このクエリを使用してください。 :

SELECT
   [Lx_AuditColumn].[auditColumnPK],
   CONVERT(NVARCHAR(204), [Lx_AuditColumn].[newValueString])
FROM
   [dbo].[Lx_AuditColumn] [Lx_AuditColumn]
INNER JOIN
   [dbo].[Lx_AuditTable] [Lx_AuditTable] ON [Lx_AuditColumn].[auditTableFK] = [Lx_AuditTable].[auditTablePK]
WHERE
   [Lx_AuditTable].[createdDate] >=  @P1
   AND
   [Lx_AuditTable].[createdDate] <=  @P2
ORDER BY
   [Lx_AuditColumn].[auditColumnPK] DESC
于 2012-08-24T09:53:47.273 に答える
0

この問題に対する洗練された解決策を提供することはできませんが (インデックス、統計、インデックス付きビューなどの通常のことを試すことは別として)、問題をハックして解決することはできます。

構文を使用するようにクエリを変換しJOIN、ヒントを適用します。

INNER HASH JOIN ...

これにより、ハッシュ結合も強制され、結合順序も修正されます。

SQL Server はスキーマとデータの変更に適応できなくなるため、これは好ましくありません。

于 2012-08-24T19:07:05.483 に答える
0

oldValueString と newValueString を NVARCHAR(255) に変更したところ、少し良くなりました。ただし、「通常」に戻ったのは、短縮された列を使用してテーブルを強制的に再作成した後です。偽の nvarchar(10) 列を追加し、デザイン モードを使用して int に変換し (つまり、デザイナーに新しいテーブルを作成してデータをコピーさせる)、余分な列を削除しました。サーバーをバウンスするか、他の何かでこの問題を解決できたかもしれませんが、サーバーをバウンスすることなく、このように行うことができました。

于 2012-08-26T06:07:35.300 に答える