iT邦幫忙

0

SQL 關聯變慢問題請教

  • 分享至 

  • xImage

您好:
語法大致如下

;with a as(

),b as(

),c as(
    處理A
)select * from  c 
  left join (
       ....資料查詢J01
  ) j01 on ...
  left join (
      ....資料查詢J02
  ) j02  on...

只要我用join J02 這一段,原來篩選時間由1秒內 慢到5秒
而我講 ....資料查詢J02 , 放到CTE 內一個查詢 ,他很快
, j02_CTE (
....資料查詢J02
)

但是 我在將
select * from c
left join J02_CTE
也是變慢

最後,我只能間原來的查詢,先寫到 #temp

再用#temp join left join (
....資料查詢J02
) j02 on...

結果一下子就出來了

這要如何找出問題

另外,原本有一個日期轉換的func,若再原來的語法下,轉換也是整個拖慢
若我用#temp 再來轉換,也是一下子就出來。

請問有什麼方式可以找到問題
執行計畫,也沒有出現遺漏索引要處理

https://ithelp.ithome.com.tw/upload/images/20240510/20104095fRiOvhc4u8.png

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
I code so I am
iT邦高手 1 級 ‧ 2024-05-10 08:46:21

變慢主要原因都是未充分運用最佳索引,建議仔細檢視執行計畫,每一段是否都用到最佳的索引,也可以比較查詢很快的SQL與很慢的SQL執行計畫之間的差異。

noway iT邦研究生 3 級 ‧ 2024-05-10 09:25:53 檢舉

您好:如附圖
這是比較兩個執行計畫的總攬
但如何比較差異,不太會看
謝謝

-----1. 秀出資料,共6秒
WITH (... ) 先撈出快速查出的資料, 寫入 #temp ==>查詢成本 61%

再用 #temp left join ( 加入後較慢的) ==>查詢成本 0%

----2. 秀出資料,共1秒
WITH (... )
left join ( 加入後較慢的) ==>查詢成本 39%

查看步驟中是否有scan table,如果有表示未使用到索引,另外,附圖select into #temp 有使用平行處理,可能也是原因。

0
cloud1991
iT邦見習生 ‧ 2024-05-10 09:37:42

你這種情況我有聽前輩分享過
SQL會自己判斷最佳的執行計畫,
但要是你加入的表越多那此執行計畫可能越不準確

要解決此問題有三種方法
1.建立索引
2.強制使用索引
3.建立臨時表(讓執行計畫重新判斷

所以你使用#temp 速度反而會變快
然後前輩推薦第3種,因為建立索引會花費內存,除非是必要否則不會去建立

0

要使用JOIN滿以下有幾點要特別的注意

1.ON的條件式,兩邊的表一定要使用有索引的欄位。
2.不要使用運算式的方式處理。
3.能不要用到 GROUP 就不要用,(當然,我了解有些情況是沒辦法)
4.不需要 ORDER
5.大資料量的不要用JOIN。如真的要用,最好搭配子查尋再處理。

認真來說,我現在已經是偏好使用資料關連容器的做法。也就是ORM。
JOIN的方式已經很少用了。

noway iT邦研究生 3 級 ‧ 2024-05-14 14:46:18 檢舉

您好:盡量去配合這些注意事項
所以我有先子查詢好在去JOIN,但就變慢了....
且神奇的是, 沒有加入這一個變慢的join時,單獨用一個FUNCTION去計算日期,結果也變慢...

請問您說的「資料關連容器的做法」是?這是是用於 類似C# 與 SERVER端的做法嗎?
目前都是用報表,鎖已會件PROC 寫出結果,呈現
謝謝

「單獨用一個FUNCTION去計算日期,結果也變慢...」
其實這個動作就是我說的第2點了。
當然也不是說不要用。只是要很小心使用。但能不用就不用。
因為很容易一個沒處理好就會造成全表搜尋而變慢。

ORM全名是叫 Object Relational Mapping
簡單來說,就是將資料庫轉成一種物件使用的概念。
在關聯的部份來說。一般SQL語法都是用JOIN。

而在ORM是各自SELECT資料後,再進行組合。
簡單說個例子好了。

像是一個SQL是

SELECT * FROM db1 
LEFT JOIN db2 ON (db2.id=db1.id)
WHERE id IN (1,2,3,4,5)

在ORM則會先

SELECT * FROM db1 WHERE id IN (1,2,3,4,5)
SELECT * FROM db2 WHERE id IN (db1拿到的對應ID值)

然後再組合到一個物件內如

[
    {
        "id":1
        "db2:{
            id:1
            data:""
        }
    },
    {
        "id":2
        "db2:{
            id:2
            data:""
        }
    },
    ....................
]

上面只是簡單的例子,但實際上應用的範圍很廣。

不過ORM也不是萬能的就是了。
因為建立了物件處理的關係。
它有機會會使用比較大量的記憶體。
如果應用的不好的情況下。

我要發表回答

立即登入回答