如果我有条件地 select 更多列,为什么这个 SQL 语句的执行时间会增加?
Why does this SQL statement increase in execution time if I conditionally select more columns?
我有一个脚本,其中包含多个写入临时表的查询。每个查询都建立在前一个查询的基础上,获取前一个查询的结果并对其执行其他操作。脚本在写入 #Data2
.
后 1 秒内运行
根据名为 @show
的用户参数,有条件地 select 写入 #Data2
的查询之后的下一个查询。当我有条件地 select 只有 1 列(见下文)时,它会在大约 1 秒内运行。
select
(case when 1 in (select use_object from dbo.DelimitedSplit8K(@show,','))
then d.vend_num
else null
end) vend_num
into
#Show
from
#Data2 d
但是, 当我对 53 列执行此操作时,查询执行时间变为 1 分 39 秒(见下文)。为什么是这样?理论上,查询应该只决定包含或不包含该列。为什么这在计算上会很昂贵?
select
(case when 1 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.vend_num else null end) vend_num
, (case when 2 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.terms_code else null end) terms_code
, (case when 3 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.last_purch else null end) last_purch
, (case when 4 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.purch_ytd else null end) purch_ytd
, (case when 5 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pay_ytd else null end) pay_ytd
, (case when 6 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.vend_remit else null end) vend_remit
, (case when 7 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.curr_code else null end) curr_code
, (case when 8 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.bank_code else null end) bank_code
, (case when 9 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pay_type else null end) pay_type
, (case when 10 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pur_acct else null end) pur_acct
, (case when 11 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.vendname else null end) vendname
, (case when 12 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.fax_num else null end) fax_num
, (case when 13 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.telex_num else null end) telex_num
, (case when 14 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pay_hold else null end) pay_hold
, (case when 15 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pay_hold_date else null end) pay_hold_date
, (case when 16 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pay_hold_reason else null end) pay_hold_reason
, (case when 17 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.sitename else null end) sitename
, (case when 18 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.siteaddress else null end) siteaddress
, (case when 19 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.city else null end) city
, (case when 20 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.state else null end) state
, (case when 21 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.zip else null end) zip
, (case when 22 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.county else null end) county
, (case when 23 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.country else null end) country
, (case when 24 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.FSMAApproved else null end) FSMAApproved
, (case when 25 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.FSMAAuditDatetime else null end) FSMAAuditDatetime
, (case when 26 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.FSMAAuditEditor else null end) FSMAAuditEditor
, (case when 27 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.vend_seq else null end) vend_seq
, (case when 28 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.interaction_id else null end) interaction_id
, (case when 29 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.interaction_stat else null end) interaction_stat
, (case when 30 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.topic else null end) topic
, (case when 31 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.Uf_CheckLevel else null end) Uf_CheckLevel
, (case when 32 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.approbation_type else null end) approbation_type
, (case when 33 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.submitted_date else null end) submitted_date
, (case when 34 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.approver else null end) approver
, (case when 35 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.approval_date else null end) approval_date
, (case when 36 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.rejector else null end) rejector
, (case when 37 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.rejection_date else null end) rejection_date
, (case when 38 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.vendstat else null end) vendstat
, (case when 39 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.po_num else null end) po_num
, (case when 40 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.po_orderdate else null end) po_orderdate
, (case when 41 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.po_stat else null end) po_stat
, (case when 42 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.po_invnum else null end) po_invnum
, (case when 43 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.po_invdate else null end) po_invdate
, (case when 44 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.poi_line else null end) poi_line
, (case when 45 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.poi_release else null end) poi_release
, (case when 46 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.poi_item else null end) poi_item
, (case when 47 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.poi_stat else null end) poi_stat
, (case when 48 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.qty_ordered else null end) qty_ordered
, (case when 49 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.qty_received else null end) qty_received
, (case when 50 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.due_date else null end) due_date
, (case when 51 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.rcvd_date else null end) rcvd_date
, (case when 52 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.poi_itemdesc else null end) poi_itemdesc
, (case when 53 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.u_m else null end) u_m
into #Show
from
#Data2 d
您可以通过更简单的方式完成此操作,而无需涉及另一个临时 table 并且无需调用此昂贵的函数 53 次:
DECLARE @show varchar(255) = '1,3';
SELECT vend_num = MIN(CASE y.value WHEN 1 THEN d.vend_num END),
terms_code = MIN(CASE y.value WHEN 2 THEN d.terms_code END),
last_purch = MIN(CASE y.value WHEN 3 THEN d.last_purch END)--,
-- ...
FROM #Data2 AS d
OUTER APPLY dbo.DelimitedSplit8K(@show,',') AS y;
当然我同意上面的评论,你应该考虑 table-valued parameters 而不是传递逗号分隔的字符串;那么你就可以加入反对 TVP 而不是进行任何昂贵的分裂。
如果您真的想使用一个函数,您应该查看其中几个拆分函数的性能测试,并可能考虑一个更好的替代方案(参见 this and this)。
在 SQL Server 2016(和 Azure SQL 数据库)中,您将能够使用 STRING_SPLIT()
, which is a surprisingly well-performing native option. See this, this, this, and this.
我有一个脚本,其中包含多个写入临时表的查询。每个查询都建立在前一个查询的基础上,获取前一个查询的结果并对其执行其他操作。脚本在写入 #Data2
.
根据名为 @show
的用户参数,有条件地 select 写入 #Data2
的查询之后的下一个查询。当我有条件地 select 只有 1 列(见下文)时,它会在大约 1 秒内运行。
select
(case when 1 in (select use_object from dbo.DelimitedSplit8K(@show,','))
then d.vend_num
else null
end) vend_num
into
#Show
from
#Data2 d
但是, 当我对 53 列执行此操作时,查询执行时间变为 1 分 39 秒(见下文)。为什么是这样?理论上,查询应该只决定包含或不包含该列。为什么这在计算上会很昂贵?
select
(case when 1 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.vend_num else null end) vend_num
, (case when 2 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.terms_code else null end) terms_code
, (case when 3 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.last_purch else null end) last_purch
, (case when 4 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.purch_ytd else null end) purch_ytd
, (case when 5 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pay_ytd else null end) pay_ytd
, (case when 6 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.vend_remit else null end) vend_remit
, (case when 7 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.curr_code else null end) curr_code
, (case when 8 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.bank_code else null end) bank_code
, (case when 9 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pay_type else null end) pay_type
, (case when 10 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pur_acct else null end) pur_acct
, (case when 11 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.vendname else null end) vendname
, (case when 12 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.fax_num else null end) fax_num
, (case when 13 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.telex_num else null end) telex_num
, (case when 14 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pay_hold else null end) pay_hold
, (case when 15 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pay_hold_date else null end) pay_hold_date
, (case when 16 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.pay_hold_reason else null end) pay_hold_reason
, (case when 17 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.sitename else null end) sitename
, (case when 18 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.siteaddress else null end) siteaddress
, (case when 19 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.city else null end) city
, (case when 20 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.state else null end) state
, (case when 21 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.zip else null end) zip
, (case when 22 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.county else null end) county
, (case when 23 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.country else null end) country
, (case when 24 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.FSMAApproved else null end) FSMAApproved
, (case when 25 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.FSMAAuditDatetime else null end) FSMAAuditDatetime
, (case when 26 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.FSMAAuditEditor else null end) FSMAAuditEditor
, (case when 27 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.vend_seq else null end) vend_seq
, (case when 28 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.interaction_id else null end) interaction_id
, (case when 29 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.interaction_stat else null end) interaction_stat
, (case when 30 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.topic else null end) topic
, (case when 31 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.Uf_CheckLevel else null end) Uf_CheckLevel
, (case when 32 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.approbation_type else null end) approbation_type
, (case when 33 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.submitted_date else null end) submitted_date
, (case when 34 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.approver else null end) approver
, (case when 35 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.approval_date else null end) approval_date
, (case when 36 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.rejector else null end) rejector
, (case when 37 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.rejection_date else null end) rejection_date
, (case when 38 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.vendstat else null end) vendstat
, (case when 39 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.po_num else null end) po_num
, (case when 40 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.po_orderdate else null end) po_orderdate
, (case when 41 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.po_stat else null end) po_stat
, (case when 42 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.po_invnum else null end) po_invnum
, (case when 43 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.po_invdate else null end) po_invdate
, (case when 44 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.poi_line else null end) poi_line
, (case when 45 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.poi_release else null end) poi_release
, (case when 46 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.poi_item else null end) poi_item
, (case when 47 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.poi_stat else null end) poi_stat
, (case when 48 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.qty_ordered else null end) qty_ordered
, (case when 49 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.qty_received else null end) qty_received
, (case when 50 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.due_date else null end) due_date
, (case when 51 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.rcvd_date else null end) rcvd_date
, (case when 52 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.poi_itemdesc else null end) poi_itemdesc
, (case when 53 in(select use_object from dbo.DelimitedSplit8K(@show,',')) then d.u_m else null end) u_m
into #Show
from
#Data2 d
您可以通过更简单的方式完成此操作,而无需涉及另一个临时 table 并且无需调用此昂贵的函数 53 次:
DECLARE @show varchar(255) = '1,3';
SELECT vend_num = MIN(CASE y.value WHEN 1 THEN d.vend_num END),
terms_code = MIN(CASE y.value WHEN 2 THEN d.terms_code END),
last_purch = MIN(CASE y.value WHEN 3 THEN d.last_purch END)--,
-- ...
FROM #Data2 AS d
OUTER APPLY dbo.DelimitedSplit8K(@show,',') AS y;
当然我同意上面的评论,你应该考虑 table-valued parameters 而不是传递逗号分隔的字符串;那么你就可以加入反对 TVP 而不是进行任何昂贵的分裂。
如果您真的想使用一个函数,您应该查看其中几个拆分函数的性能测试,并可能考虑一个更好的替代方案(参见 this and this)。
在 SQL Server 2016(和 Azure SQL 数据库)中,您将能够使用 STRING_SPLIT()
, which is a surprisingly well-performing native option. See this, this, this, and this.