2016-06-30 18 views
0

私はテーブルの関連フィールドが、私はから最新の20台の販売を抽出する必要がSQL Serverの2014テーブル/クエリの最適化

Username, ItemID, Description, CreatedDate, CountryID 

ある異なる店舗の売上を含む

dbo.Store_000 
dbo.Store_001 
.... 
dbo.Store_216 

、のセットを持っていますすべてのストアと私は次のクエリを書いた:

select top 20 UserName, ItemID, Description, CreatedDate, CountryID 
FROM ( 
    SELECT UserName, ItemID, Description, CreatedDate, CountryID FROM dbo.Store_000 
    UNION ALL 
    SELECT UserName, ItemID, Description, CreatedDate, CountryID FROM dbo.Store_001 
    UNION ALL 
    SELECT UserName, ItemID, Description, CreatedDate, CountryID FROM dbo.Store_002 
    ..... 
    ... 
    UNION ALL 
    SELECT UserName, ItemID, Description, CreatedDate, CountryID FROM dbo.Store_216     
) ii 
order by ii.createdDate desc 

現在、テーブルには200MレコードR)

そのため、処理時間を短縮するために、私はテーブルごとに、次のインデックス作成:

CREATE NONCLUSTERED INDEX I2_Store000 ON dbo.Store_000 
    (UserName) 
INCLUDE (itemId, Description, CreatedDate, CountryID) 
WITH (
    PAD_INDEX = OFF, 
    DROP_EXISTING = OFF, 
    STATISTICS_NORECOMPUTE = OFF, 
    SORT_IN_TEMPDB = OFF, 
    ONLINE = OFF, 
    ALLOW_ROW_LOCKS = ON, 
    ALLOW_PAGE_LOCKS = ON) 
ON [PRIMARY] 

をそれはまだあまりにも(私たちのマシンにいくつかの分)

は、あなたがどのように改善するか提案することができますかかりますクエリやインデックスを処理時間を短縮するには?

ソートフィールドなので、CreatedDateに基づいてインデックスを作成する必要がありますか?

もし役に立つことがあれば、HEREはMSSMS実行計画を見つけることができます。

おかげ

+0

Eralperは正しいです。また、レコードをカーソルとして扱い、本質的に21の異なるクエリを実行することによって、データセット理論を無視しています。 インターネットには、thoughtbot.com、blog.SQLAuthority、TECHNETなどのクエリ作成に関する生産的なチュートリアルが豊富に用意されています。クエリの簡単な再読み込みについては、[Thoughtbotのページ](https://robots.thoughtbot.com/back-to-basics-sql)を参照してください。 –

+0

こんにちは、レコードをカーソルとして扱うことで、 'Data Set Theory 'とはどういう意味ですか?基本的に21の異なるクエリを実行していますか?それについて何かを見つけることができます。 – Joe

+0

データベース言語を言う1つの方法は、C++のような行単位の言語ではなく、テーブル(データセット)全体を扱うことです。 SQLMagの[T-SQLの基礎:Thinking In Sets](http://sqlmag.com/t-sql/t-sql-foundations-thinking-sets) –

答えて

2

ただ、パフォーマンスのために、私は、その後、約17台* 20 = 340行

ある新しい派生テーブルから新しいトップ20を選択CreatedDateに順各テーブルから上位20行を選択する必要があります

小さいテーブルを扱う方が簡単になることを願っています。私は本当にその結果に疑問を抱いています。

+0

こんにちは、迅速な答えのためにありがとう..実際に状況が改善しましたが、十分ではありません:今は約4分かかるが、内部のソートを削除するには約1秒かかるので、sortedを避けるためにcreatedDateに基づいてインデックスを作成しなければならないと思います。しかし、別のインデックスがあるので、このインデックスを展開するか、または2番目のインデックスを作成する方が良いかどうかを理解する必要があります。 – Joe

+0

@Joeそのインデックスは何ですか?あなたが持っている唯一の "述語"は 'createdDate'と' TOP'でソートしています。 'UserName'のインデックスはどのように役立つのでしょうか? –

+0

さて、これは実際に私が既にこのテーブルに持っているインデックスです。なぜなら、このテーブルをUsernameで他のテーブルと結合する必要があるからです。インクルードに 'CreatedDate'を追加しますが、あまり役に立ちません。いくつかの200Mレコードのインデックスを作成する – Joe

0

最初の(そしてより速い)オプションは、サブクエリでTOP 20を実行してから、外側の選択を並べ替えることです。

select top 20 UserName, ItemID, Description, CreatedDate, CountryID 
FROM ( 
    SELECT TOP 20 UserName, ItemID, Description, CreatedDate, CountryID FROM dbo.Store_000 ORDER BY CreatedDate DESC 
    UNION ALL 
    SELECT TOP 20 UserName, ItemID, Description, CreatedDate, CountryID FROM dbo.Store_001 ORDER BY CreatedDate DESC 
    UNION ALL 
    SELECT TOP 20 UserName, ItemID, Description, CreatedDate, CountryID FROM dbo.Store_002ORDER BY CreatedDate DESC 
    ..... 
    ... 
    UNION ALL 
    SELECT TOP 20 UserName, ItemID, Description, CreatedDate, CountryID FROM dbo.Store_216 ORDER BY CreatedDate DESC     
) ii 
order by ii.createdDate desc 

各テーブルに必要なインデックスは、このようになります(インデックス名は例です)。

CREATE NONCLUSTERED INDEX [IX_Store_000_CreatedDate_Desc_Incl] ON [dbo].[Store_000] ([CreatedDate] DESC) 
INCLUDE ([UserName],[ItemID],[Description],[CreatedDate],[CountryID]) 

このオプションを定期的に呼び出す場合は、インデックス付きのビューを作成することもできます。インデックス付きビューには不利な点や不利な点がありますので、自分で電話をしてください。

https://www.brentozar.com/archive/2013/11/what-you-can-and-cant-do-with-indexed-views/

https://www.simple-talk.com/sql/learn-sql-server/sql-server-indexed-views-the-basics/

SQL Server - Creating an Indexed View

0

クエリを最適化することができることを使用することができ、他の技術があります。 今、UNION ALLが適切です。これは、各テーブルの値が一意である必要があるからです。

アレックスマルテッリWhat is the difference between JOIN and UNION?

からJOINはデカルト積とサブセットそれする間UNIONは、互いの後にクエリから行を置く - 完全に異なる動作を制御します。UNIONの簡単な例:

mysql> SELECT 23 AS bah 
    -> UNION 
    -> SELECT 45 AS bah; 
+-----+ 
| bah | 
+-----+ 
| 23 | 
| 45 | 
+-----+ 2 rows in set (0.00 sec) similary trivial example of JOIN: 

mysql> SELECT * FROM 
    -> (SELECT 23 AS bah) AS foo 
    -> JOIN 
    -> (SELECT 45 AS bah) AS bar 
    -> ON (33=33); 
+-----+-----+ 
| bah | bah | 
+-----+-----+ 
| 23 | 45 | 
+-----+-----+ 1 row in set (0.01 sec) 
  • ALL 20+テーブル内の述語を使用。

UNION ALLが有効かもしれないが、それはまだ代わりTOP 20を識別するために、テーブル全体をソートする必要があり、店は常に与えられ、30日の期間内に20社の以上の売上高を持っていると仮定すると、使用DATEADD又はDATEDIFF比較する前に返す行の数を制限するの比較をbooleanで行うことができます。

  • USE INDEX ...右の列

ONは明らかに、あなたのレポートは、その時INDEXESと論理的なものを使用する必要があります。 CLUSTERED INDEXESは、構築および維持するのに費用がかかりません。

あなたは名前がユニークかもしれないが、SQL Serverは名前を比較していないことを知っています...それはDATESを比較しています。したがって、createdDateINDEXを作成してください。

  • のUSE検索引数(探索引数)

SQL Serverが、それはすべてのレコードを通じてたびに行かなければならないと考えている場合であっても最高の練られた計画を台無しにすることができます。 FUNCTIONまたは変数は、以下のような述語の両側で使用されている場合:

createdDATE BETWEEN DATEADD(DD, createdDate, 30) AND CAST(GETDATE() AS DATETIME2)

SQL Serverは、値を比較する前に、テーブル全体またはINDEXリスト(TABLE/INDEX SCAN)を通過するしかありません。代わりに、このようにそれを並べ替える:

createdDATE >= DATEADD(DD, -30, GETDATE())

は、このクエリで結果を比較して、どのようCreatedDateに上のINDEXは時間を改善:

SELECT UserName, ItemID, Description, CreatedDate, CountryID 
FROM ( 
    SELECT TOP 20 UserName, ItemID, [Description], CreatedDate, CountryID FROM dbo.Store_000 
    WHERE CreatedDate >= DATEADD(DD, -30, GETDATE()) 
    UNION ALL 
    SELECT TOP 20 UserName, ItemID, [Description], CreatedDate, CountryID FROM dbo.Store_001 
    WHERE CreatedDate >= DATEADD(DD, -30, GETDATE()) 
    UNION ALL 
    SELECT TOP 20 UserName, ItemID, [Description], CreatedDate, CountryID FROM dbo.Store_002 
    WHERE CreatedDate >= DATEADD(DD, -30, GETDATE()) 
    ..... 
    ... 
    UNION ALL 
    SELECT TOP 20 UserName, ItemID, [Description], CreatedDate, CountryID FROM dbo.Store_216 
    WHERE CreatedDate >= DATEADD(DD, -30, GETDATE()) 
) ii 
-- ORDER BY CreatedDate DESC /*Unless you must, drop the ORDER BY. */ 
+0

これはすべて、リレーショナルデータを使用する例です。 :) –