简体   繁体   English

缓慢的sql脚本优化

[英]slow sql script optimization

I have a query like: 我有一个查询,如:

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

all the tables t_approved_phonenumber, t_message and t_log have a lot of records. 所有表t_approved_phonenumber,t_message和t_log都有很多记录。 and all the IDs are primary key, phone_number column has index. 并且所有ID均为主键,phone_number列具有索引。 sometimes my query is very slow. 有时我的查询很慢。 Is there any way to speed it up? 有什么办法可以加快速度吗?

thanks, 谢谢,

Maybe make an index on t_log with first column phone_number and second column c_id so that the second exists can just use this index and -dependent on the DBMS - may not even have to access the table t_log itself. 也许用第一列phone_number和第二列c_idt_log上建立索引,以便第二个存在可以使用该索引,并且-取决于DBMS-甚至不必访问表t_log本身。 Declaring the index unique promotes its usage for the optimizer - but of course you only can do this if it is really unique. 声明索引唯一会促进优化程序使用它-但是,只有在索引真正唯一时,您才能执行此操作。

And of course, make an index on m_time if there is none so far, this would probably help the row_number() . 当然,如果到目前为止没有索引,请在m_time上建立索引,这可能对row_number()有所帮助。

Try to replace correlated subqueries with plain "left join" subqueries as they usually perform better. 尝试用简单的“左联接”子查询替换相关的子查询,因为它们通常表现更好。 Regular subquery is run just once, opposite to correlated one which is run against each row. 常规子查询仅运行一次,与针对每行运行的相关子查询相反。 It also is more flexible - you can add some more data to subqueries if needed. 它还更加灵活-如果需要,您可以向子查询添加更多数据。 Your query should look like this (errors possible - don't have Management Studio right now): 您的查询应如下所示(可能会出现错误-现在没有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

In my experience joins are much better than select in the predicate. 以我的经验, joins比选择谓词要好得多。 try this query. 试试这个查询。

I assume that for each t_message there is at least one call for each Phone_Number in t_message so I'm using INNER JOIN instead of left join in the second JOIN . 我假设对于每个t_message,至少每个Phone_Number中的t_message都有一个呼叫,所以我使用INNER JOIN而不是第二个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

anyway, the indexes suggested by @FrankPl can help to gain much more performance, 无论如何,@ FrankPl建议的索引可以帮助获得更高的性能,

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM