[英]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 中引入的那樣。
然后有三件事立即引起人們的注意:
user_id
上使用TO_CHAR
,有時不使用。 該列應以相同的方式(即具有相同的數據類型)存儲在各個表中。 如果不是這種情況,訪問可能會變得非常慢,因為可能不使用索引。GROUP BY
不使用聚合函數。 這意味着你SELECT DISTINCT
,只是有點混淆。 這就提出了一個問題:為什么必須刪除重復項? 它們是如何產生的? 你可能會用不適當的連接自己生產它們嗎? 處理太大的中間結果並稍后刪除重復項是一項昂貴的操作。id
的列應該是表的主鍵。 那么,為什么還要根據 ID 再次使用對 select 的子查詢到 select 的 ID 呢? 你會得到完全相同的行。 只需直接應用標准即可。 仔細觀察,我們發現您的查詢中有兩次表pdw_lsw_tracking_point_value
,但您並沒有真正使用它。 tpv 在tpv
上task_id
以鏈接pro
和lt
,但您也可以直接在task_id
上加入pro
和lt
。 tp
在tracking_point_id
和tracking_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.