SQL Server 2014存储过程速度较慢
我有一个存储过程来计算收据,直到今天我还没有遇到任何问题,直到我不得不在一个有100000行的数据库中执行它。它太慢了,至少运行了3个小时,但还没有完成 有没有办法优化这一点 代码如下:SQL Server 2014存储过程速度较慢,sql,sql-server,loops,stored-procedures,Sql,Sql Server,Loops,Stored Procedures,我有一个存储过程来计算收据,直到今天我还没有遇到任何问题,直到我不得不在一个有100000行的数据库中执行它。它太慢了,至少运行了3个小时,但还没有完成 有没有办法优化这一点 代码如下: Declare @sousTotal numeric(16,2), @TotalTx1 numeric(18,4), @TotalTx2 numeric(18,4), @TotalTx3 numeric(18,4), @Taux1 numeric(18,4), @Taux
Declare @sousTotal numeric(16,2),
@TotalTx1 numeric(18,4),
@TotalTx2 numeric(18,4),
@TotalTx3 numeric(18,4),
@Taux1 numeric(18,4),
@Taux2 numeric(18,4),
@Taux3 numeric(18,4),
@totalEscompte numeric(16,2),
@totalFacture numeric(16,2),
@MontantPaiement numeric(16,2)
Begin
BEGIN TRANSACTION;
BEGIN TRY
select top 1 @Taux1 = TauxTaxe1,@Taux2 = TauxTaxe2 ,@Taux3 = TauxTaxe3 from tbFactureEntete where ID = @IdFacture and IDCompagnie = @IDCie
select @sousTotal =sum(sousTotal),@TotalTx1 = sum(totalTx1),@TotalTx2 = sum(totalTx2),@TotalTx3 = sum(totalTx3),
@totalEscompte = sum(totalEscompte ),@totalFacture = sum(totalFacture) from(
select SUM(isnull(A.TotalLigne,0)) AS sousTotal ,
case taxe1 when 0 then 0
when 1 then SUM(isnull(A.TotalLigne,0)) * @Taux1 / 100
end AS totalTx1,
case taxe2 when 0 then 0
when 1 then SUM(isnull(A.TotalLigne,0)) * @Taux2 / 100
end AS totalTx2,
case taxe3 when 0 then 0
when 1 then SUM(isnull(A.TotalLigne,0)) * @Taux3 / 100
end AS totalTx3,
sum(isnull(MontantEscompte,0)) as totalEscompte ,sum(isnull(TotalLigne,0)) + case taxe1 when 0 then 0
when 1 then SUM(isnull(A.TotalLigne,0)) * @Taux1 / 100
end +
case taxe2 when 0 then 0
when 1 then SUM(isnull(A.TotalLigne,0)) * @Taux2 / 100
end +
case taxe3 when 0 then 0
when 1 then SUM(isnull(A.TotalLigne,0)) * @Taux3 / 100
end as totalFacture
from tbfactureDetail A
where IdFacture = @IdFacture and A.IDCompagnie = @IDCie
group by taxe1,taxe2,taxe3) as AA
select @MontantPaiement = SUM(MontantPaiement) from tbFacturePaiement
where IdFacture = @IdFacture
update tbFactureEntete
set Total_AvantTaxe = @sousTotal,
totalTaxe1 = @TotalTx1,
totalTaxe2 = @TotalTx2,
totalTaxe3 = @TotalTx3,
TotalEscompte = isnull(@totalEscompte,0),
TotalFacture = isnull(@totalFacture,0),
TotalPaiementCR = isnull(@MontantPaiement,0) ,
TotalSolde = isnull(@totalFacture,0) - isnull(@MontantPaiement,0)
where ID = @IdFacture and IDCompagnie = @IDCie
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH;
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
return
End
再次感谢 根据表TBFactoryDetail中IdFacture和IDCompagnie的基数,如果缺少索引,则索引将有助于解决问题 如果存在许多不同的IdCompagnie值,则许多不同的IDFacture值
CREATE NONCLUSTERED INDEX IX_NewIdx_Name
ON tbfactureDetail (IdFacture,IdCompagnie)
如果每个IDfacture的idcompagni相对较少,则可以使用Include
CREATE NONCLUSTERED INDEX IX_NewIdx_Name
ON tbfactureDetail (IdFacture)
INCLUDE (IdCompagnie)
我认为这在数学上是相同的,对于代码来说更为优化
BEGIN TRY
select top 1 @Taux1 = TauxTaxe1
, @Taux2 = TauxTaxe2
, @Taux3 = TauxTaxe3
from tbFactureEntete
where ID = @IdFacture and IDCompagnie = @IDCie
select @sousTotal =sum(isnull(A.TotalLigne,0))
, @TotalTx1 = sum(taxe1 * isnull(A.TotalLigne,0) * @Taux1 / 100)
, @TotalTx2 = sum(taxe2 * isnull(A.TotalLigne,0) * @Taux2 / 100)
, @TotalTx3 = sum(taxe3 * isnull(A.TotalLigne,0) * @Taux3 / 100)
, @totalEscompte = sum(isnull(MontantEscompte,0) )
, @totalFacture =
sum(taxe1 * isnull(A.TotalLigne,0) * @Taux1 / 100) +
sum(taxe2 * isnull(A.TotalLigne,0) * @Taux2 / 100) +
sum(taxe3 * isnull(A.TotalLigne,0) * @Taux3 / 100)
from tbfactureDetail A
where IdFacture = @IdFacture and A.IDCompagnie = @IDCie
select @MontantPaiement = SUM(MontantPaiement)
from tbFacturePaiement
where IdFacture = @IdFacture
update tbFactureEntete
set Total_AvantTaxe = @sousTotal
, totalTaxe1 = @TotalTx1
, totalTaxe2 = @TotalTx2
, totalTaxe3 = @TotalTx3
, TotalEscompte = isnull(@totalEscompte,0)
, TotalFacture = isnull(@totalFacture,0)
, TotalPaiementCR = isnull(@MontantPaiement,0)
, TotalSolde = isnull(@totalFacture,0) - isnull(@MontantPaiement,0)
where ID = @IdFacture and IDCompagnie = @IDCie
END TRY
您是否尝试使用运行查询?是否检查了锁?表结构是什么?你的表上有什么索引?这里也有一些逻辑问题。前1名,无订购人。似乎还存在一些潜在的正常化问题。当您开始看到重复组(TauxTaxe1、TauxTaxe2、TauxTaxe3)时,这是一个红旗,表明该表可能违反了1NF。@SeanLange不要真的不同意您的第一点,但如果任何ID/IDCompagnie组合只有一个唯一的Taxe 1、2、3组合,则使用TOP是有意义的,而无需订购人。要达到同一个目标,总比不一样好。如果是这样的话,你的第二点就更有道理了。