sql查询性能改进
我需要优化一个查询。我有两张桌子:sql查询性能改进,sql,performance,query-optimization,Sql,Performance,Query Optimization,我需要优化一个查询。我有两张桌子: tblcard(carid int,SerialNumber varchar(15),clientID) tblTransaction(TransactionID int,SerialNumber Varchar(15),transactiondatetime,) 我需要列出交易中涉及的所有卡的日期间隔、客户名称以及所有卡的首次交易日期 以下是我所做的: select tra.serialNumber, cli.clientName,
(tblcard
)carid int,SerialNumber varchar(15),clientID
(tblTransaction
)TransactionID int,SerialNumber Varchar(15),transactiondatetime,
select
tra.serialNumber,
cli.clientName,
(select top 1 tra.Transactiondate
from tblTransaction tra
where tra.SerialNumber = car.SerialNumber
order by tra.TransactionDate)
from
tblTransaction tra
left join
tblCard car on car.SerialNumber = tra.SerialNumber
left join
tblClient cli on car.ClientID = cli.ClientID
where
--date conditions
但考虑到事务非常多,此查询运行速度非常慢(超过3分钟)。你对如何优化这一点有什么想法吗?执行计划会有所帮助。如果可能的话,用
内部连接替换左侧连接可能会有所帮助。从性能的角度来看,使用子查询也是一个糟糕的想法。相反,您可能希望使用视图或CTE:
with LatestTransactions (SerialNumber, TransactionDate)
as
(
select
SerialNumber, max(TransactionDate) as TransactionDate
from tblTransaction
group by SerialNumber
)
select
tra.serialNumber,
cli.clientName,
lt.TransactionDate
from tblTransaction tra
left join LatestTransactions lt on lt.SerialNumber = tra.SerialNumber
left join tblCard car on car.SerialNumber = tra.SerialNumber
left join tblClient cli on car.ClientID = cli.ClientID
where
--date conditions
当然,如果您没有使用正确的索引,它可能不会有多大帮助。这就是为什么查看查询执行计划很重要的原因。查询在哪里花费时间?为什么?您能否以合理的方式限制数据集?在某些列上引入新索引会有帮助吗?为什么要加入序列号,它是一个15个字符长的字符串,而不是某个标识列?Luaan,你的答案很好,我认为这是一个更可读的答案(不管tblclient表是否缺失)
尝试将子查询替换为密集\u秩
聚合(oracle语法):
可能遗漏了一些索引。执行计划可以澄清这一点。请提供有关所用DBMS、现有索引、日期条件示例和执行计划的信息。有关第三个表tblClient
和示例输出的信息也会有所帮助。
select tblTransaction.TransactionDate, Mindate.SerialNumber, Mindate.TransactionDate
from tblTransaction
outer apply (select MIN(tra.Transactiondate) TransactionDate, car.SerialNumber
from tblTransaction tra
INNER JOIN tblCard car on car.SerialNumber = tra.SerialNumber
where car.SerialNumber = tblTransaction.SerialNumber group by car.SerialNumber) Mindate
where tblTransaction.TransactionDate between '2013-05-05' and '2014-05-05'
select
tra.serialNumber,
cli.clientName,
MIN(tra.Transactiondate)
KEEP (DENSE_RANK FIRST ORDER BY tra.TransactionDate)
OVER (PARTITION BY tra.SerialNumber) AS transactiondate
from
tblTransaction tra
left join
tblCard car on car.SerialNumber = tra.SerialNumber
left join
tblClient cli on car.ClientID = cli.ClientID
where
--date conditions