2

数百万行のテーブルでいくつかの深刻なパフォーマンスの問題が発生しており、かなり迅速に結果を得ることができるはずだと感じています。これが私が持っているもの、私がそれをどのようにクエリしているのか、そしてそれがどれくらいの時間がかかっているのかを要約したものです:

  • SQL Server 2008 Standardを実行しているため、現在、パーティショニングはオプションではありません

  • 過去30日間の特定のアカウントのすべての広告枠のすべてのビューを集計しようとしています。

  • すべてのビューは次のテーブルに保存されます。

CREATE TABLE [dbo]。[LogInvSearches_Daily](
    [ID] [bigint] IDENTITY(1,1)NOT NULL、
    [Inv_ID] [int] NOT NULL、
    [Site_ID] [int] NOT NULL、
    [LogCount] [int] NOT NULL、
    [LogDay] [smalldatetime] NOT NULL、
 CONSTRAINT[PK_LogInvSearches_Daily]主キーがクラスター化されました
((
    [ID] ASC
)WITH(PAD_INDEX = OFF、STATISTICS_NORECOMPUTE = OFF、IGNORE_DUP_KEY = OFF、ALLOW_ROW_LOCKS = ON、ALLOW_PAGE_LOCKS = ON、FILLFACTOR = 90)ON [PRIMARY]
)[プライマリ]で
  • このテーブルには132,000,000レコードがあり、4ギガを超えています。

  • テーブルからの10行のサンプル:

ID Inv_ID Site_ID LogCount LogDay
-------------------- ----------- ----------- -------- --- -----------------------
1 486752 48 14 2009-07-21 00:00:00
2 119314 51 16 2009-07-21 00:00:00
3 313678 48 25 2009-07-21 00:00:00
4 298863 0 1 2009-07-21 00:00:00
5 119996 0 2 2009-07-21 00:00:00
6 463777 534 7 2009-07-21 00:00:00
7 339976 503 2 2009-07-21 00:00:00
8 333501 570 4 2009-07-21 00:00:00
9 453955 0 12 2009-07-21 00:00:00
10 443291 0 4 2009-07-21 00:00:00

(影響を受ける10行)
  • LogInvSearches_Dailyに次のインデックスがあります。
/ ******オブジェクト:インデックス[IX_LogInvSearches_Daily_LogDay]スクリプト日付:2010年5月12日11:08:22 ****** /
CREATE NONCLUSTERED INDEX [IX_LogInvSearches_Daily_LogDay]ON[dbo]。[LogInvSearches_Daily]
((
    [LogDay] ASC
)。
INCLUDE([Inv_ID]、
[LogCount])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]
  • 特定のアカウントIDのインベントリからのみインベントリをプルする必要があります。インベントリにもインデックスがあります。

次のクエリを使用してデータを集計し、上位5つのレコードを取得しています。このクエリは現在、5行を返すのに24秒かかります。

StmtText
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------
トップ5を選択
    Sum(LogCount)ASビュー
    、DENSE_RANK()OVER(ORDER BY Sum(LogCount)DESC、Inv_ID DESC)ASランク
    、Inv_ID
FROM LogInvSearches_Daily D(NOLOCK)
どこ
    LogDay> DateAdd(d、-30、getdate())
    AND EXISTS(
        SELECT NULL FROM propertyControlCenter.dbo.Inventory(NOLOCK)WHERE Acct_ID = 18731 AND Inv_ID = D.Inv_ID
    )。
GROUP BY Inv_ID


(影響を受ける1行)

StmtText
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------
  | --Top(TOP EXPRESSION:((5)))
       |-シーケンスプロジェクト(DEFINE:([Expr1007] =density_rank))
            |-セグメント
                 |-セグメント
                      | --Sort(ORDER BY:([Expr1006] DESC、[D]。[Inv_ID] DESC))
                           | --Stream Aggregate(GROUP BY:([D]。[Inv_ID])DEFINE:([Expr1006] = SUM([LOALogs]。[dbo]。[LogInvSearches_Daily]。[LogCount]as[D]。[LogCount] ))))
                                | --Sort(ORDER BY:([D]。[Inv_ID] ASC))
                                     |-ネストされたループ(内部結合、外部参照:([D]。[Inv_ID]))
                                          |-ネストされたループ(内部結合、外部参照:([Expr1011]、[Expr1012]、[Expr1010]))
                                          | | --Compute Scalar(DEFINE:(([Expr1011]、[Expr1012]、[Expr1010])= GetRangeWithMismatchedTypes(dateadd(day、(-30)、getdate())、NULL、(6))))
                                          | | |-コンスタントスキャン
                                          | | --Index Seek(OBJECT:([LOALogs]。[dbo]。[LogInvSearches_Daily]。[IX_LogInvSearches_Daily_LogDay] AS [D])、SEEK:([D]。[LogDay]> [Expr1011]AND[D]。[ LogDay] <[Expr1012])注文済み)
                                          | --Index Seek(OBJECT:([propertyControlCenter]。[dbo]。[Inventory]。[IX_Inventory_Acct_ID])、SEEK:([propertyControlCenter]。[dbo]。[Inventory]。[Acct_ID] =(18731)AND [ propertyControlCenter]。[dbo]。[Inventory]。[Inv_ID]=[LOA

(影響を受ける13行)

CTEを使用して最初に行を取得して集計しようとしましたが、それ以上速く実行されず、基本的に同じ実行プランが得られました。

(影響を受ける1行)
StmtText
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------
--SHOWPLAN_TEXTをオンに設定します。
with getSearches AS(
        選択する
            LogCount
-、DENSE_RANK()OVER(ORDER BY Sum(LogCount)DESC、Inv_ID DESC)ASランク
            、D.Inv_ID
        FROM LogInvSearches_Daily D(NOLOCK)
            内部結合propertyControlCenter.dbo.InventoryI(NOLOCK)ON Acct_ID = 18731 AND I.Inv_ID = D.Inv_ID
        どこ
            LogDay> DateAdd(d、-30、getdate())
--GROUP BY Inv_ID
)。

SELECT Sum(LogCount)ASビュー、Inv_ID
getSearchesから
GROUP BY Inv_ID


(影響を受ける1行)

StmtText
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------------------------------------
  | --Stream Aggregate(GROUP BY:([D]。[Inv_ID])DEFINE:([Expr1004] = SUM([LOALogs]。[dbo]。[LogInvSearches_Daily]。[LogCount]as[D]。[LogCount] ))))
       | --Sort(ORDER BY:([D]。[Inv_ID] ASC))
            |-ネストされたループ(内部結合、外部参照:([D]。[Inv_ID]))
                 |-ネストされたループ(内部結合、外部参照:([Expr1008]、[Expr1009]、[Expr1007]))
                 | | --Compute Scalar(DEFINE:(([Expr1008]、[Expr1009]、[Expr1007])= GetRangeWithMismatchedTypes(dateadd(day、(-30)、getdate())、NULL、(6))))
                 | | |-コンスタントスキャン
                 | | --Index Seek(OBJECT:([LOALogs]。[dbo]。[LogInvSearches_Daily]。[IX_LogInvSearches_Daily_LogDay] AS [D])、SEEK:([D]。[LogDay]> [Expr1008]AND[D]。[ LogDay] <[Expr1009])注文済み)
                 | --Index Seek(OBJECT:([propertyControlCenter]。[dbo]。[Inventory]。[IX_Inventory_Acct_ID] AS [I])、SEEK:([I]。[Acct_ID] =(18731)AND[I]。[ Inv_ID]=[LOALogs]。[dbo]。[LogInvSearches_Daily]。[Inv_ID]as[D]。[Inv_ID])ORDERED FORWARD)

(影響を受ける8行)


(影響を受ける1行)

実行プランで優れたインデックスシークを取得しているとすると、これをより高速に実行するにはどうすればよいですか?

アップデート:

これは、DENSE_RANK()なしで実行された同じクエリであり、実行にはまったく同じ24秒かかり、同じ基本クエリプランが得られます。

StmtText
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------
--SHOWPLAN_TEXTをオンに設定
トップ5を選択
    Sum(LogCount)ASビュー
    、Inv_ID
FROM LogInvSearches_Daily D(NOLOCK)
どこ
    LogDay> DateAdd(d、-30、getdate())
    AND EXISTS(
        SELECT NULL FROM propertyControlCenter.dbo.Inventory(NOLOCK)WHERE Acct_ID = 18731 AND Inv_ID = D.Inv_ID
    )。
GROUP BY Inv_ID
ビューによる注文、Inv_ID
(影響を受ける1行)

StmtText
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------
  | --Sort(TOP 5、ORDER BY:([Expr1006] ASC、[D]。[Inv_ID] ASC))
       | --Stream Aggregate(GROUP BY:([D]。[Inv_ID])DEFINE:([Expr1006] = SUM([LOALogs]。[dbo]。[LogInvSearches_Daily]。[LogCount]as[D]。[LogCount] ))))
            | --Sort(ORDER BY:([D]。[Inv_ID] ASC))
                 |-ネストされたループ(内部結合、外部参照:([D]。[Inv_ID]))
                      |-ネストされたループ(内部結合、外部参照:([Expr1010]、[Expr1011]、[Expr1009]))
                      | | --Compute Scalar(DEFINE:(([Expr1010]、[Expr1011]、[Expr1009])= GetRangeWithMismatchedTypes(dateadd(day、(-30)、getdate())、NULL、(6))))
                      | | |-コンスタントスキャン
                      | | --Index Seek(OBJECT:([LOALogs]。[dbo]。[LogInvSearches_Daily]。[IX_LogInvSearches_Daily_LogDay] AS [D])、SEEK:([D]。[LogDay]> [Expr1010]AND[D]。[ LogDay] <[Expr1011])注文済み)
                      | --Index Seek(OBJECT:([propertyControlCenter]。[dbo]。[Inventory]。[IX_Inventory_Acct_ID])、SEEK:([propertyControlCenter]。[dbo]。[Inventory]。[Acct_ID] =(18731)AND [ propertyControlCenter]。[dbo]。[Inventory]。[Inv_ID]=[LOALogs]。[dbo]。[LogInvS

(影響を受ける9行)


ありがとう、

ダン

4

3 に答える 3

1

私はあなたの質問全体をまだ読んでいませんが (すぐにそれについて説明します)、初期のコメントに答えるために: SQL Server 2008 標準版ではパーティションビューを使用できます。Enterprise エディションに限定されているのは、パーティション分割されたテーブル(明らかにより柔軟です) です。

分割ビュー情報: http://msdn.microsoft.com/en-us/library/ms190019.aspx

より広い質問については、そこに DENSE_RANK が本当に必要かどうか知りたいです。DENSE_RANK 内の ORDER BY とクエリ自体の ORDER BY を混同しているのではないかと思います。現状では、SQL Server は ORDER BY 句が指定されていない限りレコードの順序を保証しないため、TOP 5 は 5 つの未定義のレコードを返します (これは行っていません)。次のように、ORDER BY を DENSE_RANK からクエリ全体の ORDER BY に移動すると、必要に応じてレコードが出力され、高価な DENSE_RANK 集計関数が不要になります。

SELECT TOP 5
    SUM([LogCount]) AS [Views],
    [Inv_ID]
FROM [LogInvSearches_Daily] D (NOLOCK)
WHERE 
    [LogDay] > DateAdd(d, -30, getdate())
    AND EXISTS(
        SELECT *
        FROM Inventory (NOLOCK)
        WHERE Acct_ID = 18731
            AND Inv_ID = D.Inv_ID
    )
GROUP BY
    Inv_ID
ORDER BY
    [Views] DESC,
    [Inv_ID]

アップデート:

時間はおそらくここで使い果たされています:

|--Sort(ORDER BY:([D].[Inv_ID] ASC))

次のようなカバリング インデックスを作成してみてください。

CREATE NONCLUSTERED INDEX [IX_LogInvSearches_Daily_Perf] ON [dbo].[LogInvSearches_Daily] 
(
    [Inv_ID] ASC,
    [LogDay] ASC
)
INCLUDE
(
    [LogCount]
)

ORDER BY も少し変更したことに注意してください (Inv_ID は、DESC ではなく ASC でソートされるようになりました)。この変更によって結果に問題が生じることはないと思いますが、グループ化されたのと同じ順序で行が返されるため、パフォーマンスが向上する可能性があります (これは無関係かもしれませんが!)。

于 2010-05-12T16:33:22.290 に答える
1

パーティショニングはさておき、

あなたのテーブルよりも大きなテーブルでの経験に基づいて、データを一時テーブル (テーブル変数ではない) に抽出し、それを集計します。すべてのクエリではなく、より複雑なクエリです。

それ以外は、Daniel Renshaw の DENSE_RANK に関する観察に同意します。

[Inv_ID]、[LogCount] をインデックスに移動することも考えます (含めないでください。おそらく DESC ソートを使用します)。

于 2010-05-12T17:03:50.173 に答える
0

Acct_ID は Inventory テーブルにあり、それ自体へのインデックス (IX_Inventory_Acct_ID) を持っているようです。おそらく、Inventory に (Acct_Id, Inv_Id) のインデックスがあり、LogInvSearches_Daily が (Inv_Id, LogDay) の周りにクラスター化されている (または少なくともインデックス化されている) 場合は、もっとうまくいくでしょう。

ところで、LogInvSearches_Daily.ID の現在のクラスタリング インデックスが何を買っているのかわかりません。ディスク上で近い ID を持つレコードを閉じるためにインポートするのはなぜですか?

于 2010-05-12T19:43:21.597 に答える