0

我有一个像这样的查询:

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 列有索引。有时我的查询很慢。有什么办法可以加快速度吗?

谢谢,

4

3 回答 3

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
于 2013-08-21T19:23:54.167 回答
0

以我的经验joins,比谓词中的选择要好得多。试试这个查询。

我假设对于每个 t_message 至少有一个调用Phone_Numbert_message所以我INNER JOIN在第二个中使用而不是 left 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 建议的索引可以帮助获得更多的性能,

于 2013-08-21T19:28:06.887 回答
0

也许在t_log第一列phone_number和第二列上创建一个索引,c_id以便第二个存在可以只使用这个索引并且 - 依赖于 DBMS - 甚至可能不必访问表t_log本身。声明索引唯一会促进它对优化器的使用——但当然,只有当它真的唯一时,你才能这样做。

当然,如果到目前为止还没有 m_time 索引,这可能会对row_number().

于 2013-08-21T18:22:31.777 回答