2017-08-30 61 views
0

下面是該查詢:查詢在一個數據集中運行速度較慢,但​​在另一個較大的數據集中速度較快; MSSQL服務器;不同的執行計劃。爲什麼?

select nd1.ansos_id 
from nursdate nd1 
where nd1.division_id = 2 
    and nd1.unit_id = 19 
    and nd1.nursdate_start_date = 
      (select min(nd2.nursdate_start_date) 
      from nursdate nd2 
      where nd2.ansos_id = nd1.ansos_id 
       and nd2.nursdate_start_date >= all 
         (select nd3.nursdate_start_date 
         from nursdate nd3 
         where nd3.ansos_id = nd1.ANSOS_ID 
          and nd3.nursdate_start_date <= '2017-08-13 00:00:00')) 

下面是兩個數據集真

  • 統計最新的;
  • 索引碎片整理
  • 這兩個數據集的常規屬性是相同的:例如:整理;
  • 此外,2個數據集的數據量相同。其實更快的有更多的數據

現在它需要~8秒運行在1數據集,但< 1秒在另一個數據集。 下面是在慢數據集中的2個數據集之間

  1. &「執行的次數」「的行的實際數」的執行計劃差天文更高
  2. 較快一個還具有附加的節點「索引後臺「

截圖#1:相同的查詢,在一個數據集中 enter image description here

截圖#2緩慢執行計劃:相同的查詢,SPEE dy在另一個數據集中執行計劃 enter image description here

如何解決此問題?我能做些什麼才能讓它在第一個數據集中快速運行? 謝謝!

[編輯]較慢執行計劃:(注意整個「nursdate」表只有99K行) https://www.brentozar.com/pastetheplan/?id=r1ZFFuNt-

更快的執行計劃:(注意整個「nursdate」表具有333K行是以某種方式更快) https://www.brentozar.com/pastetheplan/?id=rJYMc_EKb

[編輯]這裏是數據捲上的一些信息。在「MMT」的人有更少的數據,但運行速度較慢

--mmt cnt: 99347 
select count(*) 
from mmt_sqa_v60.mmtsqav60.nursdate nd1 

--heo cnt: 333275 
select count(*) 
from heo_sqa_v60_2k12.heosqav602k12.nursdate nd1 

--mmt cnt: 2403 
select count(*) 
from mmt_sqa_v60.mmtsqav60.nursdate nd1 
where nd1.division_id = 2 
and nd1.unit_id = 19 
and nd1.nursdate_start_date <= '2017-08-13 00:00:00' 


--heo cnt: 5537 
select count(*) 
from heo_sqa_v60_2k12.heosqav602k12.nursdate nd1 
where nd1.division_id = 1 
and nd1.unit_id = 20 
and nd1.nursdate_start_date <= '2017-08-13 00:00:00' 
+1

請使用此工具發佈兩個執行計劃:https://www.brentozar.com/pastetheplan/ – Eli

+1

你的意思是兩個數據集?如果他們使用不同的表,你應該有兩個不同的查詢?如果查詢使用不同的參數,那麼我們也需要兩個查詢,以便我們可以比較 –

+1

你的問題的答案就在這裏[[實際行數]&[慢數據集中的執行次數]天文數字更高]。 410萬行和9k行。執行計劃可能會有所不同,因爲我們正在討論數據量差異的大小。 –

回答

0

神祕解決了。這是一個數據問題。這裏就是大量的「執行計劃」的來自:

select count(*) 
from mmtsqav60.NURSDATE ndArea 
left outer join mmtsqav60.NURSDATE ndRelated on ndRelated.ANSOS_ID = 
ndArea.ANSOS_ID 
where ndArea.DIVISION_ID=2 and ndArea.UNIT_ID=19; 

結果是4157613這是究竟有多少行的執行計劃說,通過指標返回尋求對ND2和ND3。因爲,上述邏輯本質上是WSM中的nursdate查詢要求數據庫服務器執行的操作 - 查找某個區域的所有記錄,然後爲每個此類記錄查找該ansos_id的所有記錄。 這些數據對我們來說是不現實的數據,因爲一個單獨的「ansos_id」有數千條記錄。感謝所有在這裏幫助過的人。

0

不相關的問題,但您的查詢有一些問題。我認爲你的查詢功能找到ansos_id@date糾正我之前的任何記錄,如果我錯了。

最深層次帶來的所有ansos_id以前的日期爲@date

select nd3.nursdate_start_date 
from nursdate nd3 
where nd3.ansos_id = nd1.ANSOS_ID 
    and nd3.nursdate_start_date <= '2017-08-13 00:00:00') 

那麼以前的查詢比較對所有這些日期。

and nd2.nursdate_start_date >= all (...) 

這是非常低效的,因爲只有日期大於或等於所有日期是MAX(date)

然後你(select min(nd2.nursdate_start_date)的時候,我已經解釋只有一個日期>= to all

我會說您的查詢應該被替換爲這將返回每個@date之前的最後一條記錄ansos_id

WITH cte as ( 
    select nd1.ansos_id, nursdate_start_date, 
      RANK() OVER (PARTITION BY ansos_id 
         ORDER BY nursdate_start_date DESC) as rn 
    from nursdate nd1 
    where nd1.division_id = 2 
     and nd1.unit_id = 19 
     and nd1.nursdate_start_date <= '2017-08-13 00:00:00' 
) 
SELECT * 
FROM cte 
WHERE rn = 1 
+0

感謝您的幫助。這是一個2步查詢;步驟1:如果有任何記錄<=目標日期,則返回其中最新的一個, 步驟2:否則,如果步驟#1返回空值,則返回最早記錄>目標日期。 – riceball

+0

我的查詢執行Step1。但是你的查詢似乎沒有做第二步?可以重複日期嗎? –

+0

這個查詢不會執行第2步(這就是「min」的意思)。不,這不是重複的日期。另外我嘗試了其他的東西(在同一個數據庫服務器中都有兩個數據集)。我爲這個問題添加了一條評論。 – riceball

相關問題