gpt4 book ai didi

sql-server - 查询运行速度快,但存储过程运行速度慢

转载 作者:行者123 更新时间:2023-12-01 18:41:11 26 4
gpt4 key购买 nike

我正在使用 SQL 2005 探查器进行一些测试。

我有一个存储过程,它只运行一个 SQL 查询。

当我运行存储过程时,需要很长时间并执行 800,000 次磁盘读取。

当我独立于存储过程运行相同的查询时,它会执行 14,000 次磁盘读取。

我发现如果我使用 OPTION(recompile) 运行相同的查询,则需要 800,000 次磁盘读取。

据此,我做出(可能是错误的)假设:存储过程每次都会重新编译,这就是导致问题的原因。

有人能解释一下吗?

我已将 ARITHABORT 设置为“ON”。 (这解决了 stackoverflow 上的类似问题,但没有解决我的问题)

这是整个存储过程:

CREATE PROCEDURE [dbo].[GET_IF_SETTLEMENT_ADJUSTMENT_REQUIRED]
@Contract_ID int,
@dt_From smalldatetime,
@dt_To smalldatetime,
@Last_Run_Date datetime
AS
BEGIN
DECLARE @rv int


SELECT @rv = (CASE WHEN EXISTS
(
select * from
view_contract_version_last_volume_update
inner join contract_version
on contract_version.contract_version_id = view_contract_version_last_volume_update.contract_version_id
where contract_version.contract_id=@Contract_ID
and volume_date >= @dt_From
and volume_date < @dt_To
and last_write_date > @Last_Run_Date
)
THEN 1 else 0 end)

-- Note that we are RETURNING a value rather than SELECTING it.
-- This means we can invoke this function from other stored procedures
return @rv
END

这是我运行的一个脚本来演示该问题:

DECLARE 
@Contract_ID INT,
@dt_From smalldatetime,
@dt_To smalldatetime,
@Last_Run_Date datetime,
@rv int


SET @Contract_ID=38
SET @dt_From='2010-09-01'
SET @dt_To='2010-10-01'
SET @Last_Run_Date='2010-10-08 10:59:59:070'


-- This takes over fifteen seconds
exec GET_IF_SETTLEMENT_ADJUSTMENT_REQUIRED @Contract_ID=@Contract_ID,@dt_From=@dt_From,@dt_To=@dt_To,@Last_Run_Date=@Last_Run_Date

-- This takes less than one second!
SELECT @rv = (CASE WHEN EXISTS
(
select * from
view_contract_version_last_volume_update
inner join contract_version
on contract_version.contract_version_id = view_contract_version_last_volume_update.contract_version_id
where contract_version.contract_id=@Contract_ID
and volume_date >= @dt_From
and volume_date < @dt_To
and last_write_date > @Last_Run_Date
)
THEN 1 else 0 end)


-- With recompile option. Takes 15 seconds again!
SELECT @rv = (CASE WHEN EXISTS
(
select * from
view_contract_version_last_volume_update
inner join contract_version
on contract_version.contract_version_id = view_contract_version_last_volume_update.contract_version_id
where contract_version.contract_id=@Contract_ID
and volume_date >= @dt_From
and volume_date < @dt_To
and last_write_date > @Last_Run_Date
)
THEN 1 else 0 end) OPTION(recompile)

最佳答案

好的,我们之前也遇到过类似的问题。

我们解决这个问题的方法是在 SP 内设置本地参数,这样

DECLARE @LOCAL_Contract_ID int, 
@LOCAL_dt_From smalldatetime,
@LOCAL_dt_To smalldatetime,
@LOCAL_Last_Run_Date datetime

SELECT @LOCAL_Contract_ID = @Contract_ID,
@LOCAL_dt_From = @dt_From,
@LOCAL_dt_To = @dt_To,
@LOCAL_Last_Run_Date = @Last_Run_Date

然后我们使用 SP 内的本地参数,而不是传入的参数。

这通常为我们解决了问题。

我们认为这是由于参数嗅探造成的,但没有任何证据,抱歉...X-)

编辑:

看看Different Approaches to Correct SQL Server Parameter Sniffing一些富有洞察力的示例、解释和修复。

关于sql-server - 查询运行速度快,但存储过程运行速度慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3995386/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com