2017-04-05 3 views
2

最適化が必要なクエリがあり、わからない方法があります。本当に速いが、それはほぼ15分クエリ以外のSQL最適化

@colorCombinationはほぼ24,000行

productattributesは11,000を返していました、除くと選択の両方を除き、ステートメントの実行がなけれ

declare @tempTable table(color1 int, color2 int, color3 int, color4 int, newToken uniqueidentifier default newid(), ordinal int identifier(1,1)) 

insert into @tempTable 
select color1, color2, color3, color4 
from @colorCombination 
except 
select c1.color as color1, c2.color as color2, c3.color as color3, c4.color as color4 
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' 

:これは、SQLスクリプトです行

データベースにまだない13,000のものを見つけて挿入する必要があるため、私は例外を使用しました。

これは、SQL Server上で実行されている2008

ではなく除くを使用しての欠落しているレコードを取得するための良い方法はありますか?

答えて

2

非常に少ない行のパフォーマンスが低いのは、テーブル変数とその実行計画にどのように影響するかによって発生します。

この回答は、クラスタ化されていないインデックスのあるテンポラリテーブルを(color1, color2, color3, color4)に使用しています。元のテーブル変数にはどの色でもnot nullが指定されていなかったので、nullの値を使用できるとします。一致しない場合は、代理オブジェクトIdを削除し、4つの色の列にクラスタ化インデックスを使用できます。 nullを許可するには、not exists()の代わりにexceptに戻って切り替えます。 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()を使用する(またはselectdistinctを追加するが、それはパフォーマンスヒットがかかります)することができます

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 
) 
+0

を私もしたいですtempテーブル/テーブル変数がまったく使われていない理由を調べたいのですが?クエリの結果を何回か使用する必要がない限り、私はその部分を排除して直接クエリを使用します...これはより大きな目的にも左右されます。 –

+0

迅速な対応をありがとう!私は後でそれを試し、あなたに知らせるでしょう。どうもありがとうございます。私はスクリプトを編集し、それは一時テーブルの列を持っています。それを挿入した後、私は3つのテーブルに不足している行を一括して挿入する必要があります –

+0

私は存在しませんでした..悲しいことに、今何か16分かかる –