2017-09-18 17 views
2

ビューを介して結合しようとしている2つのメインテーブルを持つSQL Azureデータベースがあります。私はそれが働いているが、実行時間は2分を超えています。ここで 日付間のSQLクエリと従業員名に基づく

は私が扱ってるメインテーブルと列です:

TransactionsTable:

PostedDate   | EmployeeFirstName | EmployeeLastName | DollarsCollected | UserName 
--------------------------------------------------------------------------------------------- 
09/08/2017 09:05 am | 'John'   | 'Smith'   |   42.25 | 'john.smith' 
09/08/2017 09:07 am | 'Jane'   | 'Jones'   |   58.50 | 'jane.jones' 
09/08/2017 09:15 am | 'Tom'    | 'Holland'  |   62.75 | 'tom.holland' 
09/08/2017 09:17 am | 'John'   | 'Smith'   |   48.50 | 'john.smith'  
09/08/2017 09:19 am | 'Jane'   | 'Jones'   |   32.25 | 'jane.jones' 

CustomerHistory

CustomerID | StartDate   | Duration | UserName  | TransactionType 
----------------------------------------------------------------------------- 
     1 | 09/08/2017 09:02 am |  600 | 'john.smit'h | 'PropertyTax' 
     2 | 09/08/2017 09:03 am |  500 | 'tom.holland' | 'TagRenewal' 
     3 | 09/08/2017 09:04 am |  450 | 'jane.jones' | 'PropertyTax' 
     4 | 09/08/2017 09:12 am |  700 | 'john.smith' | 'TagRenewal' 
     5 | 09/08/2017 09:16 am |  300 | 'jane.jones' | 'TagRenewal' 

ので、契約はここにある - 唯一の従業員を持つことができます一度に1つの顧客。トランザクションがいつ投稿されたか分かっており、従業員が投稿した内容が分かっている場合は、StartDateおよび​​を使用して、そのトランザクションの総計の一種としてCustomerHistoryテーブルにその情報を接続できる必要があります。​​はEndDateと等しいとみなしてください。だから、ここで私はこれを実現するために実行しようとしているクエリです:参考

SELECT 
    * 
FROM 
    CustomerHistory 
    JOIN TransactionsTable ON 
     CustomerHistory.UserName = TransactionsTable.UserName 
     AND 
     TransactionsTable.PostedDate >= CustomerHistory.StartDate 
     AND 
     TransactionsTable.PostedDate <= DATEADD(ss, CustomerHistory.StartDate, CustomerHistory.Duration) 

は、私がUserNameフィールド上のインデックスと同様に日付フィールドを持っています。私が参加したいと思っている各テーブルからさらに多くのデータの列があるので、私はここで私のテーブルを単純化していると言えば十分です。私はSQL Serverで実行計画を実行しました。ハッシュマッチは実行時間の約38%を要し、トランザクションテーブルのテーブルスキャンは42%かかります。私はSQLでまともですが、私がここで扱っているものほどリソース集中的なクエリを掘り下げたことは一度もありませんし、サーバをこのように実行しようとするとかなりの負担をかけることになります。

誰でも手助けできますか?

+0

です。私は、名前、姓、およびユーザー名のフィールドを持つUsersという3番目のテーブルに参加することができます。これを実行しても、このクエリではまだ2〜3分で実行されています。 この目的のために、両方のテーブルにUserNameフィールドがあると仮定します。私はこれを反映するために私の最初の質問を編集します。 – Shane

+0

'UserNameフィールドと日付フィールドにインデックスがあります.'日付インデックスの' Duration'カラムを 'INCLUDE'と見なすと、SQL Serverはそのインデックスを使って' StartDate 'と' Duration'は同じインデックスからです –

+0

テーブルとビューはどちらですか?あなたの質問は言いません。 – Dai

答えて

0

クエリがSARGableでないため、スピードアップが難しいです。永続的な計算カラムを追加すると、あなたのクエリにはうまくいくはずです。このは、DML(挿入、更新、削除)を遅くすることができるので、この記事を読む必要があります。参照のためのあなたのテーブルの

マイ作成スクリプト(SQLフィドルhttp://sqlfiddle.com/#!6/f1a39/8):

Create Table dbo.TransactionsTable 
(
    PostedDate Datetime, 
    EmployeeFirstName Varchar(100), 
    EmployeeLastName Varchar(100), 
    DollarsCollected Money, 
    UserName Varchar(100) 
); 

Create Table dbo.CustomerHistory 
(
    CustomerID Int, 
    StartDate DateTime, 
    Duration Int, 
    UserName Varchar(100), 
    TransactionType Varchar(100) 
); 


Insert Into dbo.TransactionsTable 
Values 
('09/08/2017 09:05 am','John','Smith',42.25 , 'john.smith'), 
('09/08/2017 09:07 am','Jane','Jones',58.50 , 'jane.jones'), 
('09/08/2017 09:15 am','Tom','Holland',62.75 , 'tom.holland'), 
('09/08/2017 09:17 am','John','Smith',48.50 , 'john.smith'),  
('09/08/2017 09:19 am','Jane','Jones',32.25 , 'jane.jones'); 
GO 

Insert Into dbo.CustomerHistory 
    Values (1,'09/08/2017 09:02 am',600,'john.smith' ,'PropertyTax'), 
     (2,'09/08/2017 09:03 am',500,'tom.holland','TagRenewal'), 
     (3,'09/08/2017 09:04 am',450,'jane.jones','PropertyTax'), 
     (4,'09/08/2017 09:12 am',700,'john.smith','TagRenewal'), 
     (5,'09/08/2017 09:16 am',300,'jane.jones','TagRenewal'); 
Go 

あなたはこのインデックスを持っていることを確認してください。

CREATE NONCLUSTERED INDEX ix_test1 
    ON TransactionsTable(UserName,PostedDate) 
    Include (EmployeeFirstName,EmployeeLastName,DollarsCollected); 
GO 

永続的な列を追加できますか?そして、インデックス列

Alter Table CustomerHistory 
Add EndDate As (DateAdd(ss,Duration,StartDate)) Persisted; 
GO 
CREATE NONCLUSTERED INDEX ix_test2 
    ON CustomerHistory(UserName,StartDate,EndDate) 
    Include(CustomerID,TransactionType); 
GO 

は、ここで私は少し私のサンプルを単純化ここは、クエリ

SELECT * 
FROM CustomerHistory AS A 
INNER JOIN TransactionsTable AS B 
    ON A.UserName = B.UserName 
    AND B.PostedDate Between A.StartDate And A.EndDate; 
+0

ここに本当に良い提案があり、私はそれらをすべて実装しました。残念ながら、クエリの速度の向上はありません。私は一致する最初のエントリを探すだけでクエリが高速化できると思っています。言い換えれば、クエリは開始日と終了日の間に投稿されたすべてのトランザクションを探していますが、実際には1つだけにする必要があります。それで、それは最初のものを見て止めることができます。私はrow()とpartition_byを使用してこれを行う必要があると思いますが、それは私の強い訴訟ではありません。何かご意見は? – Shane

+0

どのようなクエリを使用していますか?また、実行計画をスクリーンショットし、 "set statistics io on"でクエリを実行し、メッセージ結果を質問に追加することもできます。 – Stephan

関連する問題