[英]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_id
在t_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.