Eu tenho as 4 consultas SQL abaixo que combino em um conjunto de resultados no final.
Suponho que, como estou operando nas mesmas tabelas em cada uma das seções SQL, existe uma maneira legal de obter meus resultados de uma consulta SQL unificada.
Atualmente estou fazendo assim:
select
[date] = CONVERT(DATE, M.crdate),
[tally sent to smc w/ attachment] = count(*) ,
[total MB size] = sum(cast(AD.Size as decimal (10,2)) )/1024/1024
into #tmp_Attachments_Sent_To_smc
from AttachmentDetail AD
inner join MessageAttachment MA on AD.AttachmentId = MA.AttachmentId
inner join MessageRecipient MR on MA.MessageId = MR.MessageId
inner join Message M on MR.MessageId = M.id
where AD.isinline <>1 and MR.RecipientTypeId =2 and left(mr.EmailAddress,4)='smc+'
GROUP BY CONVERT(DATE, M.crdate)
ORDER BY [date] DESC;
--select * from #tmp_Attachments_Sent_To_smc
select
[date] = CONVERT(DATE, M.crdate),
[tally sent from smc w/ attachment] = count(*) ,
[total MB size] = sum(cast(AD.Size as decimal (10,2)) )/1024/1024
into #tmp_Attachments_Sent_from_smc
from AttachmentDetail AD
inner join MessageAttachment MA on AD.AttachmentId = MA.AttachmentId
inner join MessageRecipient MR on MA.MessageId = MR.MessageId
inner join Message M on MR.MessageId = M.id
where AD.isinline <>1 and MR.RecipientTypeId =1 and left(mr.EmailAddress,4)='smc+'
GROUP BY CONVERT(DATE, M.crdate)
ORDER BY [date] DESC;
select
[date] = CONVERT(DATE, M.crdate),
[grand total sent to smc] = count(*) ,
[total MB size sent to smc] = sum(cast(Size as decimal ) )/1024/1024
into #tmp_Sent_to_smc
from Message M
where MessageSourceId=2
GROUP BY CONVERT(DATE, crdate)
ORDER BY [date] DESC;
select
[date] = CONVERT(DATE, M.crdate),
[grand total sent from smc] = count(*) ,
[total MB size sent from smc] = sum(cast(Size as decimal ) )/1024/1024
into #tmp_Sent_from_smc
from Message M
where MessageSourceId=1
GROUP BY CONVERT(DATE, crdate)
ORDER BY [date] DESC;
select A.* ,
B.[tally sent from smc w/ attachment] ,
B.[total MB size],
C.[grand total sent from smc] ,
C.[total MB size sent from smc],
D.[grand total sent to smc] ,
D.[total MB size sent to smc]
from #tmp_Attachments_Sent_To_smc A
join #tmp_Attachments_Sent_from_smc B on A.date = b.date
join #tmp_Sent_from_smc C on A.date = C.date
join #tmp_Sent_to_smc D on A.date = D.date
drop table #tmp_Attachments_Sent_To_smc
drop table #tmp_Attachments_Sent_from_smc
drop table #tmp_Sent_from_smc
drop table #tmp_Sent_to_smc
Como primeira passagem, veria se você pode eliminar as tabelas temporárias. Eu gosto de CTE , mas nem sempre eles oferecem melhor desempenho.
Caso contrário, o que provavelmente está prejudicando seu desempenho são as conversões em seus WHEREs e GROUP BY (
CONVERT(date, M.crdate)
CAST(AD.Size AS decimal(10, 2)
. Essas provavelmente estão resultando em varreduras de tabela que prejudicam você. Você também pode examinar as colunas computadas persistentes se não puder modificar os tipos de dados existentes como um significa armazenar esses itens calculados.Estou olhando para o
LEFT(mr.EmailAddress, 4)
e acho que isso também forçará uma verificação da tabela, mas acho que pode ser corrigido com ummr.EmailAddress LIKE 'smc+%'
Isso deve ser pelo menos SARGable.Nesse ponto, você deve ser capaz de examinar seus planos de consulta e determinar se um índice pode ajudar.
Além disso, prefixe suas tabelas com o esquema apropriado. Presumo que seja dbo, mas pelo que entendi, isso ajudará no plano de reutilização do cache.
Notas
billinkc
está certo. Usar uma função LEFT em uma coluna varchar não é SARGable , portanto, use LIKE. Ser compatível com SARG significa que os critérios podem ser usados em um ARGument de pesquisa em um índiceDATE
tabelas temporárias ajudará na consulta se você estiver analisando, digamos, 1.000 datas exclusivas (3 anos de dados)CAST(.. to decimal)
precisa de um especificador. Caso contrário, é equivalente a decimal(18,0). (que ainda pode ser útil para evitar a divisão inteira)Uma única consulta
O lote de consulta original:
Eu usei este DDL e DML para testar: