3

ここで一時テーブルを実装していることをよりよく理解するために、where句に基づいていくつかの列の合計を実行する必要があります

declare @tbl table(a int ,b int,c int)
insert into @tbl values(1,2,3)
insert into @tbl values(2,2,3)
insert into @tbl values(1,3,1)
insert into @tbl values(1,2,3)
insert into @tbl values(1,2,3)

そして、a、b、cの値のa、b、cob基底の合計を見つけるために; 私は次のクエリを使用しています

 SELECT (
         SELECT SUM(a) from @tbl where a=1         
         )AS a ,          
          (SELECT SUM(b) from @tbl where b=2

         )AS b ,         
          (SELECT SUM(c) from @tbl where c=3

         )AS c

私は私の友人の一人にこの仕事のために一行の質問をするように頼みます、そして彼は私に次の行を提案します

select sum((case  when a=1 then a  else null end)),
        sum((case  when b=2 then b  else null end)),
        sum((case  when c=3 then c  else null end))
         from @tbl

今、27の列と数百万のレコードがある場合に、より高速に動作するパフォーマンスについて考えていますか?

または、これを達成するための他の方法で、これら2つよりもパフォーマンスが大幅に向上します。

4

3 に答える 3

5

マーティンの答えを拡張します-それはあなたが持っているインデックスと列がどのように入力されているか(null許容かどうか)に依存します。この例を考えてみましょう。

create table tbl (id int identity primary key, a int ,b int,c int, d int)
insert tbl values(1,2,3,null)
insert tbl values(2,null,3,1)
insert tbl values(1,null,1,4)
insert tbl values(1,null,3,5)
insert tbl values(1,null,3,6)
insert tbl select a,b,c,d from tbl --10
insert tbl select a,b,c,d from tbl --20
insert tbl select a,b,c,d from tbl --40
insert tbl select a,b,c,d from tbl --80
insert tbl select a,b,c,d from tbl --160
insert tbl select a,b,c,d from tbl --320
insert tbl select a,b,c,d from tbl --640
insert tbl select a,b,c,d from tbl --1280
insert tbl select a,b,c,d from tbl --2560
insert tbl select a,b,c,d from tbl --5120
insert tbl select a,b,c,d from tbl --10240

列bはNULL可能に作成され、20%がNULL以外です。次に、テーブルに対してクエリを実行します(インデックスなし)。実行する前に、必ずCtrl-M(実際の実行プランを表示)を押してください。同じバッチで両方のクエリを実行します。つまり、両方のクエリのテキストを強調表示して実行します。

SELECT (SELECT SUM(a) from tbl where a=1) AS a ,          
       (SELECT SUM(b) from tbl where b=2) AS b ,         
       (SELECT SUM(c) from tbl where c=3) AS c

select sum((case  when a=1 then a  else null end)),
       sum((case  when b=2 then b  else null end)),
       sum((case  when c=3 then c  else null end))
from tbl

ここでは画像に飽きることはありませんが、上位のクエリに対して約75%、下位のクエリに対して25%のコストが表示される計画を見てください。これは、75%:25%= 3:1であると予想されます。これは、最初のクエリがテーブルを正確に3回通過するためです。次に、次の3つのインデックスを作成します。

create index ix_tbl_a on tbl(a)
create index ix_tbl_b on tbl(b)
create index ix_tbl_c on tbl(c)

次に、クエリバッチを(両方一緒に)再実行します。今回は、約51%から49%のコストが表示されます。かなり近いです。その理由は、(b)まばらに入力されている列はSUM、インデックスページだけから非常に簡単に取得できるためです。他の2つの列でさえ、データページ(すべての列を含む)のクラスター化インデックスよりも多くの行をインデックスページごとに取得することで役立ちます。

これを27列に拡張すると、各列のデータがまばらで、27列のそれぞれにインデックスがある場合、最初のフォームの実行が速くなる可能性があります。大きな質問ですが、それでも、おそらくごくわずかに速くなるでしょう。

于 2012-10-13T21:51:19.360 に答える
4

2番目のオプションは、テーブルのシングルパスを作成します。最初のものは複数のパスを作成します。パフォーマンスに関しては、ほとんどの場合、2番目のオプションが優れているはずです。

于 2012-10-13T17:56:08.427 に答える
3

それはあなたが持っているインデックスに依存します。

a、、bおよびcすべてにインデックスが付けられている場合、元のバージョンの方が大幅に高速になる可能性があります。特に、テーブルの大部分がどの基準も満たさない場合。

有用なインデックスがまったくない場合は、1回のスキャンに対して3回のスキャンを選択するため、CASEバージョンが高速になります。

于 2012-10-13T19:46:30.333 に答える