SQL 使用参数执行查询
SQL Query Execution using parameter
我无法弄清楚为什么基于我将参数换成实际值,查询 运行 花费的时间要长得多。
DECLARE @quarter int
DECLARE @year int
DECLARE @countOfUnitsBought int
set @year = 2009
set @quarter = 1
set @countOfUnitsBought = 4;
with res
as
(
select
o.account_id
--,orderyear
--,orderquarter
from
fmtables.[dbo].[orders] o
--cross apply(values(year(o.[ship_date]))) as a1(orderyear)
--cross apply(values(DatePart(quarter,(o.[ship_date])))) as a2(orderquarter)
where
ship_date = (select min(ship_date) from fmtables.[dbo].[orders] mo where [account_id] = o.account_id) and
total_value > 0 AND
order_status NOT LIKE 'return%' AND
order_status NOT LIKE 'cancel%' AND
order_status NOT LIKE 'freeze%' and
CAST(DatePart(quarter,(o.[ship_date])) as int) = @quarter and
year(o.[ship_date]) = @year and
(select sum(quantity) from fmtables..[orders] ox inner join fmtables..[orderlines] olx on ox.order_id = olx.order_id
where olx.order_id = o.order_id and [product_code] in(select [product_code] from fmtables..[products] where [category_code] in('1','2','3','4'))) >= @countOfUnitsBought
)
select * from res;
此查询需要 43 秒才能 运行。
现在,如果我简单地替换@quarter 并更改为文字
CAST(DatePart(quarter,(o.[ship_date])) as int) = 1 and
现在需要 1 秒。
任何人都可以告诉我为什么以及是否需要更改一些转换来提供帮助。
谢谢
斯科特
编辑:
因此,在大家的评论的帮助下,我设法让它顺利通过。
我混合使用了从输入传递参数然后传递到过程中的 'local' 变量。
alter procedure [dbo].[Lifetime_HeadsetUnits]
@inquarter int , @inyear int, @incountOfUnitsBought int
as
DECLARE @quarter int
DECLARE @year int
declare @countOfUnitsBought int
select @quarter = @inquarter
select @year = @inyear
select @countOfUnitsBought = @incountOfUnitsBought
还有
选项(优化(@quarter = 1))
作为最终输出查询的一部分。
试试这个。我重写了日期部分,以便可以使用索引,并且数据库不会对所有行进行长时间计算。换句话说,我计算了你的日期 sargable:
DECLARE @quarter int
DECLARE @year int
DECLARE @countOfUnitsBought int
set @year = 2009
set @quarter = 1
declare @from datetime = dateadd(quarter, @quarter - 1, cast(@year as char(4)))
set @countOfUnitsBought = 4;
with res
as
(
select
o.account_id
from
fmtables.[dbo].[orders] o
where
ship_date =
(select min(ship_date)
from fmtables.[dbo].[orders] mo
where [account_id] = o.account_id) and
total_value > 0 AND
order_status NOT LIKE 'return%' AND
order_status NOT LIKE 'cancel%' AND
order_status NOT LIKE 'freeze%' and
o.[ship_date] >= @quarter and
o.[ship_date] < DATEADD(QUARTER, 1, @from) and
(select sum(quantity) from fmtables..[orders] ox
inner join fmtables..[orderlines] olx on ox.order_id = olx.order_id
where [product_code] in(select [product_code] from fmtables..[products]
where [category_code] in('1','2','3','4'))) >= @countOfUnitsBought
)
select * from res;
您 运行 是 sql-server 2008 吗?有一个 bug 也可以解释您的性能问题。
我无法弄清楚为什么基于我将参数换成实际值,查询 运行 花费的时间要长得多。
DECLARE @quarter int
DECLARE @year int
DECLARE @countOfUnitsBought int
set @year = 2009
set @quarter = 1
set @countOfUnitsBought = 4;
with res
as
(
select
o.account_id
--,orderyear
--,orderquarter
from
fmtables.[dbo].[orders] o
--cross apply(values(year(o.[ship_date]))) as a1(orderyear)
--cross apply(values(DatePart(quarter,(o.[ship_date])))) as a2(orderquarter)
where
ship_date = (select min(ship_date) from fmtables.[dbo].[orders] mo where [account_id] = o.account_id) and
total_value > 0 AND
order_status NOT LIKE 'return%' AND
order_status NOT LIKE 'cancel%' AND
order_status NOT LIKE 'freeze%' and
CAST(DatePart(quarter,(o.[ship_date])) as int) = @quarter and
year(o.[ship_date]) = @year and
(select sum(quantity) from fmtables..[orders] ox inner join fmtables..[orderlines] olx on ox.order_id = olx.order_id
where olx.order_id = o.order_id and [product_code] in(select [product_code] from fmtables..[products] where [category_code] in('1','2','3','4'))) >= @countOfUnitsBought
)
select * from res;
此查询需要 43 秒才能 运行。
现在,如果我简单地替换@quarter 并更改为文字
CAST(DatePart(quarter,(o.[ship_date])) as int) = 1 and
现在需要 1 秒。
任何人都可以告诉我为什么以及是否需要更改一些转换来提供帮助。 谢谢 斯科特
编辑:
因此,在大家的评论的帮助下,我设法让它顺利通过。 我混合使用了从输入传递参数然后传递到过程中的 'local' 变量。
alter procedure [dbo].[Lifetime_HeadsetUnits]
@inquarter int , @inyear int, @incountOfUnitsBought int
as
DECLARE @quarter int
DECLARE @year int
declare @countOfUnitsBought int
select @quarter = @inquarter
select @year = @inyear
select @countOfUnitsBought = @incountOfUnitsBought
还有
选项(优化(@quarter = 1))
作为最终输出查询的一部分。
试试这个。我重写了日期部分,以便可以使用索引,并且数据库不会对所有行进行长时间计算。换句话说,我计算了你的日期 sargable:
DECLARE @quarter int
DECLARE @year int
DECLARE @countOfUnitsBought int
set @year = 2009
set @quarter = 1
declare @from datetime = dateadd(quarter, @quarter - 1, cast(@year as char(4)))
set @countOfUnitsBought = 4;
with res
as
(
select
o.account_id
from
fmtables.[dbo].[orders] o
where
ship_date =
(select min(ship_date)
from fmtables.[dbo].[orders] mo
where [account_id] = o.account_id) and
total_value > 0 AND
order_status NOT LIKE 'return%' AND
order_status NOT LIKE 'cancel%' AND
order_status NOT LIKE 'freeze%' and
o.[ship_date] >= @quarter and
o.[ship_date] < DATEADD(QUARTER, 1, @from) and
(select sum(quantity) from fmtables..[orders] ox
inner join fmtables..[orderlines] olx on ox.order_id = olx.order_id
where [product_code] in(select [product_code] from fmtables..[products]
where [category_code] in('1','2','3','4'))) >= @countOfUnitsBought
)
select * from res;
您 运行 是 sql-server 2008 吗?有一个 bug 也可以解释您的性能问题。