这么少的行的糟糕表现是由表变量以及它们如何影响执行计划造成的。
此答案在(color1, color2, color3, color4)
上使用非聚集索引的临时表。您的原始表格变量没有为任何颜色指定not null
,所以我将假定某些null
值是可以接受的。如果不是,您可以删除代理Id
并在四个颜色列上使用聚簇索引。为了允许空值,这也切换回except
而不是not exists()
。如果null
不是一个因素,那么not exists()
应该快一点。
/* step 1: existing colors in a temp table with an index */
create table #productColors (
id int not null identity (1,1) primary key clustered
, color1 int , color2 int , color3 int , color4 int
);
insert into #productColors (color1, color2, color3, color4)
select distinct
color1 = case when c.[type] = 'primary' then c.color end
, color2 = case when c.[type] = 'secondary' then c.color end
, color3 = case when c.[type] = 'other1' then c.color end
, color4 = case when c.[type] = 'other2' then c.color end
from from products p
inner join attributes c
on p.Id = c.Id
group by p.id;
create nonclustered index ix_productColors
on #productColors (color1, color2, color3, color4);
/* step 2: color combinations in a temp table with an index */
create table #colorCombinations (
id int not null identity (1,1) primary key clustered
, color1 int , color2 int , color3 int , color4 int
);
insert into #colorCombinations (color1, color2, color3, color4)
select distinct color1 , color2 , color3 , color4
from @colorCombinations;
create nonclustered index ix_colorCombinations
on #colorCombinations (color1, color2, color3, color4);
/* step 3: insert new color combinations into #tempTable */
create table #tempTable (color1 int
, color2 int
, color3 int
, color4 int
, newToken uniqueidentifier default newid()
, ordinal int identifier(1,1)
);
insert into #tempTable(color1, color2, color3, color4)
select color1, color2, color3, color4
from #colorCombination
except
select color1, color2, color3, color4
from #productColors
:关于表变量和临时表
参考
老答案:
使用except
也去复制的行你@tempTable
(这可能是最好的,而不是#temptable
的@TableVariable
这取决于你如何使用它)。
如果你不需要从@tempTable
删除重复的行,那么你可以使用not exists()
(或添加distinct
到select
,但它会采取的性能损失):
insert into @tempTable
select color1, color2, color3, color4
from @colorCombination cc
where not exists (
select 1
from products p
inner join attributes c1 on c1.pId = p. Id and c1.type = 'primary'
inner join attributes c2 on c2.pId = p. Id and c2.type = 'secondary'
inner join attributes c3 on c3.pId = p. Id and c3.type = 'other1'
inner join attributes c4 on c4.pId = p. Id and c4.type = 'other2'
where p.category = 'furniture'
and c1.color = cc.color1
and c2.color = cc.color2
and c3.color = cc.color3
and c4.color = cc.color4
)
我还喜欢询问为什么使用临时表/表变量?除非查询结果需要多次使用,否则我会消除该部分并直接使用查询......但这取决于更宏观的目的。 –
感谢您的快速响应!我稍后再尝试,并让你知道。非常感谢。我编辑了脚本,它具有临时表的列。在插入后,我需要批量插入缺失的行在3个表 –
我试过不存在..可悲的是现在需要16分钟的时间 –