2017-03-09 10 views
1

我試圖優化查詢。基本上,交易有三部分可以重複。我記錄了所有通信,但想要獲得3個部分中的「最新鮮」。這三部分都通過一個單一的中間錶鏈接起來(不幸的是),這是什麼放緩了整個事情(太多的標準化?)。強制唯一鍵以避免合併連接

有「星級」「交易」的中心,然後是中心輻條(所有由「TransactionDetails」代表,其中樞紐使用「Transactions」主鍵,然後是外部輻條(PPGDetails,TicketDetails和「TicketDetails」和「CompletionDetails」中的每一個在它們鏈接到的「TransactionDetails」中都有一行,通過主鍵。每筆交易可以有多對這些對象中的每一對。

因此,爲了獲得最近的TicketDetails交易,我使用這個視圖:

CREATE VIEW [dbo].[TicketTransDetails] AS 
select * 
from TicketDetails tkd 
join (select MAX(TicketDetail_ID) as TicketDetail_ID 
    from TicketDetails temp1 
    join TransactionDetails temp2 
    on temp1.TransactionDetail_ID = temp2.TransactionDetail_ID 
    group by temp2.Transaction_ID) qq 
on tkd.TicketDetail_ID = qq.TicketDetail_ID 
join TransactionDetails td 
on tkd.TransactionDetail_ID = td.TransactionDetail_ID 
GO 

其他2個細節類型具有相似的視圖。

然後,把所有的交易細節我想,每交易一排,我使用:

select * 
from Transactions t 
join CompletionTransDetails cpd 
on t.Transaction_ID = cpd.Transaction_ID 
left outer join TicketTransDetails tkd 
on t.Transaction_ID = tkd.Transaction_ID 
left outer join PPGTransDetails ppd 
on t.Transaction_ID = ppd.Transaction_ID 
where cpd.DateAndTime between '2/1/2017' and '3/1/2017' 

這是由設計,我想至少具有1「CompletionDetail」 ONLY的交易,但0或更多「PPGDetail」或「TicketDetail」。

此查詢返回正確的結果,但需要40秒才能在體面的服務器硬件上執行,並且在「SELECT」返回需要100%的執行計劃時間之前立即執行「合併連接(左外連接)」。

如果我在最終查詢中將連接取出爲PPGTransDetails或TicketTransDetails,它將執行時間降低到〜20秒,因此顯着改進,但仍然對大量記錄進行合併連接無關,我假設)。

當只選擇一個事務(通過where子句)時,查詢只需要大約4秒,然後查詢就會有「嵌套循環」的最後一步,這也需要大部分時間( 96%)。我希望這個查詢不到一秒鐘。

由於視圖沒有主鍵,我認爲導致合併聯接繼續進行。也就是說,我在創建模擬此功能的查詢時遇到問題 - 更不用說效率更高的查詢了。

任何人都可以幫助我認識到我可能錯過了什麼嗎?

謝謝!

--mobrien118

編輯:添加更多的信息 - 下面是有效的數據模型: Transaction Data Model

從本質上講,對於單個事務,可以有很多PPGDetails,TicketDetails和CompletionDetails,但每一個會有它自己的TransactionDetails(它們是一對一的,但不是在模型中強制實施,只是在軟件中)。

目前有:

  • 1619307 「交易」
  • 3,564518 「TransactionDetails」
  • 512644 「PPGDetails」
  • 1471826 「TicketDetails」
  • 1580043 「CompletionDetails」

目前沒有forei gn在這些項目上設置的關鍵約束或索引。

+0

你對底層表有什麼樣的索引? – pmbAustin

回答

1

首先快速備註:

這也需要的時間(96%)的很大一部分。

這是一個(常見的)誤解。 96%的人估計'block'需要多少資源。這並不意味着查詢內96%的時間花在了它上面。我遇到了這樣的情況,其中接收了一半的查詢時間上的幾乎沒有成本。

此外,您似乎認爲當您查詢/加入視圖時,系統將首先從視圖準備數據,然後再使用該結果進一步「解決查詢」。情況並非如此,系統將'擴大'視圖並執行'組合'查詢,將所有內容都考慮在內。

爲了我們理解發生了什麼,您需要向我們提供查詢計劃(如果您使用SqlSentry計劃資源管理器,則需要提供.sqlplan),這是對錶格佈局,索引,外鍵等的完整說明......以及對數據(總行數,表格之間的預期匹配等)的一點解釋......

PS:儘管每個人似乎都在鼓吹'散列連接'作爲解決所有問題的方法,嵌套循環並且合併連接通常更高效。

(試圖理解你的查詢,是這一觀點等同於你的看法?)

[編輯:不正確視圖中刪除,以避免混淆]

第二個嘗試:(想我是不是正確的這段時間)

CREATE VIEW [dbo].[TicketTransDetails] AS 
SELECT td.Transaction_ID, tkd.* 
    FROM TicketDetails tkd 
    JOIN TransactionDetails td 
    ON td.TransactionDetail_ID = tkd.TransactionDetail_ID 
    JOIN (SELECT MAX(TicketDetail_ID) as max_TicketDetail_ID, temp2.Transaction_ID 
      FROM TicketDetails temp1 
      JOIN TransactionDetails temp2 
      ON temp1.TransactionDetail_ID = temp2.TransactionDetail_ID 
     GROUP BY temp2.Transaction_ID) qq 
    ON qq.max_TicketDetail_ID = tkd.TicketDetail_ID 
    AND qq.TransactionDetail_ID = td.Transaction_ID 

查詢整個表時可能不會更快,但它應該在從Transactions表中獲取特定記錄時更快。

索引明智的,你可能想在TicketDetails(TransactionDetail_ID, TicketDetail_ID)

唯一索引,你需要類似結構的其他表偏離方向。

通過在一些思考它進一步,我認爲這將工作太:

CREATE VIEW [dbo].[TicketTransDetails] 
AS 
SELECT * 
    FROM (
      SELECT td.Transaction_ID, 
        TicketDetail_ID_rownr = ROW_NUMBER() OVER (PARTITION BY td.Transacion_ID ORDER BY tkd.TicketDetail_ID DESC), 
        tkd.* 
      FROM TicketDetails tkd 
       JOIN TransactionDetails td 
       ON td.TransactionDetail_ID = tkd.TransactionDetail_ID 
     ) xx 
WHERE TicketDetail_ID_rownr = 1 -- we want the "first one from the end" only 

看起來更具可讀性相當多的,但我不知道它會更快或不...你有比較計時和查詢計劃。

+0

不幸的是,那個查詢是不等價的 - 我想要基於組的關鍵字段是TransactionDetails.Transaction_ID(這是「集線器」表「Transactions」的主鍵的外鍵。我想找到最後一個通過主鍵)爲每個「交易」,「PPGDetail」,「TicketDetail」和「CompletionDetail」,但不幸的是,獲得「Transaction_ID」的唯一方法是徹底的中間表「TransactionDetails」... 我會更新我想我會留下關鍵細節 - 只是儘量保持它儘可能短。 – mobrien118

+0

謝謝,圖片幫助了很多,我現在將刪除我的錯誤觀點,並有一個稍後再看 – deroby

+0

通過在「TicketDetails」,「PPGDetails」以及「TicketDetails」,「PPGDetails」這三個表中的每一個的「TransactionDetail_ID」字段中創建一個「Unique Key」聚集索引,我能夠將性能提高約36% 「CompletionDetails」。還是比我希望的慢得多。我相信,如果我刪除了中間表(BIG軟件更改),我會把它降低到秒......我可憐的設計回來困擾着我。 我會有興趣聽到你可能有的任何其他想法! – mobrien118