簡體   English   中英

查詢優化(使用連接而不是子查詢)?

[英]Query optimisation (Using joins instead subquery)?

我需要有關此查詢的幫助。 我需要提高查詢的執行時間。 任何建議如何改進和優化它? 我認為子查詢是其中最有問題的部分。 知道如何更改它並使其更快嗎?

select pro.ID,lt.TASK_ID,lt.ACTIVITY_NAME, lt.CREATION_TIME as START_TIME, lt.END_TIME, lum.USERNAME, to_char((lt.END_TIME-lt.CREATION_TIME),'dd.MM.yyyy HH24:mm:ss')  AS TASK_DURATION
 from pdw_lsw_tracking_point tp, pdw_lsw_tracking_point_value tpv, pdw_tg_processtable pro, pdw_lsw_task lt, pdw_lsw_user_mappings lum
 where  tp.tracking_point_id=tpv.tracking_point_id
and pro.task_id = tpv.task_id
and lt.functional_task_id=tpv.task_id
and lt.SYSTEM_USER_ID = TO_CHAR(lum.USER_ID) AND lt.SYSTEM_ID = lum.SYSTEM_ID
and tp.TRACKING_GROUP_ID=tpv.TRACKING_GROUP_ID
and pro.ID IN (select pro.ID  from  pdw_tg_processtable pro where step=13 and time_stamp between  '01.03.21' and  '08.03.21')
group by pro.ID,lt.TASK_ID,lt.ACTIVITY_NAME, lt.CREATION_TIME, lt.END_TIME, lum.USERNAME
order by pro.ID,lt.CREATION_TIME;
select pro.ID, lt.TASK_ID, lt.ACTIVITY_NAME, lt.CREATION_TIME as START_TIME, lt.END_TIME, lum.USERNAME, to_char((lt.END_TIME-lt.CREATION_TIME),'dd.MM.yyyy HH24:mm:ss')  AS TASK_DURATION
from pdw_lsw_tracking_point tp, 
JOIN pdw_lsw_tracking_point_value as tpv ON tp.tracking_point_id=tpv.tracking_point_id
JOIN pdw_tg_processtable as pro ON pro.task_id = tpv.task_id
JOIN pdw_lsw_task as lt ON lt.functional_task_id=tpv.task_id
JOIN pdw_lsw_user_mappings as lum ON lum.SYSTEM_ID = lt.SYSTEM_ID 
where lt.SYSTEM_USER_ID = TO_CHAR(lum.USER_ID) 
and tp.TRACKING_GROUP_ID=tpv.TRACKING_GROUP_ID
and pro.ID IN (select pro.ID  from  pdw_tg_processtable pro where step=13 and time_stamp between  '01.03.21' and  '08.03.21')
group by pro.ID,lt.TASK_ID,lt.ACTIVITY_NAME, lt.CREATION_TIME, lt.END_TIME, lum.USERNAME
order by pro.ID,lt.CREATION_TIME;

您無緣無故地使用古老的連接語法。 首先要做的是清理它並使用正確的連接( INNER JOIN... ON ),正如 1992 年標准 SQL 中引入的那樣。

然后有三件事立即引起人們的注意:

  1. 有時您在user_id上使用TO_CHAR ,有時不使用。 該列應以相同的方式(即具有相同的數據類型)存儲在各個表中。 如果不是這種情況,訪問可能會變得非常慢,因為可能不使用索引。
  2. GROUP BY不使用聚合函數。 這意味着你SELECT DISTINCT ,只是有點混淆。 這就提出了一個問題:為什么必須刪除重復項? 它們是如何產生的? 你可能會用不適當的連接自己生產它們嗎? 處理太大的中間結果並稍后刪除重復項是一項昂貴的操作。
  3. 名為id的列應該是表的主鍵。 那么,為什么還要根據 ID 再次使用對 select 的子查詢到 select 的 ID 呢? 你會得到完全相同的行。 只需直接應用標准即可。

仔細觀察,我們發現您的查詢中有兩次表pdw_lsw_tracking_point_value ,但您並沒有真正使用它。 tpv 在tpvtask_id以鏈接prolt ,但您也可以直接在task_id上加入prolt tptracking_point_idtracking_group_id上加入,但隨后不再使用tp

固定user_id數據類型后,您會得到以下內容:

select 
  pro.id,
  lt.task_id,
  lt.activity_name,
  lt.creation_time as start_time,
  lt.end_time,
  lum.username,
  lt.end_time - lt.creation_time as task_duration
from pdw_tg_processtable pro 
join pdw_lsw_task lt on lt.functional_task_id = pro.task_id
join pdw_lsw_user_mappings lum on lum.system_id = lt.system_id
                              and lum.user_id = lt.system_user_id
where pro.step = 13 and pro.time_stamp between date '2021-03-01' and date '2021-03-21'
order by pro.id, lt.creation_time;

你想要這些索引:

create idx1 on pdw_tg_processtable (step, time_stamp, task_id, id);
create idx2 on pdw_tg_processtable (time_stamp, step, task_id, id);
create idx3 on pdw_lsw_task (functional_task_id, system_id, system_user_id);
create idx4 on pdw_lsw_user_mappings (system_id, system_user_id, username);
create idx5 on pdw_lsw_user_mappings (system_user_id, system_id, username);

(其中您只需要 idx1 或 idx2 以及 idx4 或 idx5。不過,我不知道是哪個。創建它們並在以后刪除未使用的。)

嘗試修改您的子查詢:

and exists
 (select pt.ID
    from pdw_tg_processtable pt
   where step=13
     and time_stamp between '01.03.21' and '08.03.21'
     and pt.id = pro.ID)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM