慢sql脚本优化

时间:2013-08-21 18:11:54

标签: sql optimization case exists

我有一个类似的查询:

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列具有索引。有时我的查询很慢。有没有办法加快速度?

感谢,

3 个答案:

答案 0 :(得分:0)

也许在t_log上使用第一列phone_number和第二列c_id制作索引,以便第二列存在可以只使用此索引并依赖于DBMS - 甚至可能没有访问表t_log本身。声明索引唯一可以促进它对优化器的使用 - 但当然,如果它真的是唯一的,你只能这样做。

当然,如果到目前为止还没有m_time的索引,这可能对row_number()有帮助。

答案 1 :(得分: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

答案 2 :(得分:0)

根据我的经验,joins比谓词中的select更好。 试试这个查询。

我认为对于每个t_message,Phone_Number中的每个t_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建议的索引可以帮助我们获得更多的性能,