2013-08-21 197 views
0

我有這樣一個查詢:慢SQL腳本優化

select row_number() over(order by m_time desc) as row, m.m_id, m_time, m_log_id 
    (case when exists(select 1 from t_approved_phonenumber where phone_number = m.c_phone_number) then 1 else 0 end) as approved, 
    (case when exists(select 1 from t_log log where log.c_id < m.m_log_id and log.phone_number = m.phone_number) then 'N' else 'Y' end) as is_first_time 
from t_message m 

所有表t_approved_phonenumber,t_message和t_log有很多的記錄。並且所有的ID都是主鍵,phone_number列有索引。有時候我的查詢很慢。有什麼方法可以加速嗎?

感謝,

+2

你忘了提,運行此查詢的SQL產品。另外,當詢問優化時,請考慮添加當前版本查詢的查詢計劃。 –

回答

0

也許使與第一列phone_number和第二列c_idt_log一個索引,使第二存在可以只使用這個指標和依賴於數據庫管理系統 - 甚至可以不訪問表t_log本身。聲明獨特的索引可以促進優化器的使用 - 但是,如果它真的是唯一的,你當然可以做到這一點。

當然,如果到目前爲止還沒有做m_time的索引,這可能會幫助row_number()

0

嘗試用簡單的「左連接」子查詢替換相關的子查詢,因爲它們通常表現更好。常規子查詢只運行一次,與每行對應的運行相反。它也更靈活 - 如果需要,您可以將更多數據添加到子查詢中。 您的查詢應該是這樣的(錯誤的可能 - 沒有Management Studio中現在):

select 
    row_number() over(order by m_time desc) as row 
    ,m.m_id 
    ,m_time 
    ,m_log_id 
    ,coalesce(approved, 0) as approved 
    ,coalesce(is_first_time, 'Y') as is_first_time 
from 
    t_message m 
    left join (select phone_number, 1 as [approved] from t_approved_phonenumber group by phone_number) as a 
    on a.phone_number = m.c_phone_number 
    left join (select phone_number, min(c_id) as c_id, 'N' as is_first_time from t_log group by phone_number) log 
    on log.c_id < m.m_log_id and log.phone_number = m.phone_number 
0

以我的經驗joins比在謂詞選擇要好得多。 試試這個查詢。

我認爲每個t_message至少有一個呼叫每個Phone_Numbert_message所以我用INNER JOIN,而不是留下參加第二JOIN

select row_number() over(order by m_time desc) as row, 
    m.m_id, 
    m_time, 
    m_log_id, 
    (case WHEN approved.phone_number IS NULL then 0 else 1 end) as approved, 
    (case when First_c_id < m.m_log_id then 'N' else 'Y' end) as is_first_time 
from t_message m 
LEFT JOIN t_approved_phonenumber approved ON m.c_phone_number = approved.phone_number 
INNER JOIN (SELECT phone_number, MIN(c_id) AS First_c_id 
      FROM t_log 
      GROUP BY phone_number) FirstLog ON FirstLog.PhoneNumber = m.phone_number 

無論如何,通過@FrankPl建議索引可以幫助獲得更多的性能,