2

次の(確かに長い)例を考えてみましょう。

サンプルコードは、2つのデータセットを作成します。データ1つは「キー」変数i、j、kを持ち、データ2はキー変数j、kと「値」変数xを持ちます。これら2つのデータセットを可能な限り効率的にマージしたいと思います。両方のデータセットは、jとkに関してインデックスが付けられています。最初のデータのインデックスは必要ないはずですが、とにかくそこにあります。

Proc SQLは、データ2のインデックスを使用しません。これは、データがリレーショナルデータベースにある場合に当てはまると思います。これは、受け入れなければならないクエリオプティマイザの単なる制限ですか?

編集:この質問への答えは「はい」です。SA​​Sはインデックスを使用してPROCSQL結合を最適化できます。次の例では、データセットの相対的なサイズが重要です。データ2がデータ1よりも比較的大きくなるようにコードを変更すると、インデックスが使用されます。データセットがソートされているかどうかは関係ありません。

* Just to control the size of the data;
%let j_max=10000;

* Create data sets;
data one;
    do i=1 to 3;
        do j=1 to &j_max;
            do k=1 to 4;
                if ranuni(0)<0.9 then output;
            end;
        end;
    end;
run;

data two;
    do j=1 to &j_max;
        do k=1 to 4;
            x=ranuni(0);
            if ranuni(0)<0.9 then output;
        end;
    end;
run;

* Create indices;
proc datasets library=work nolist;
    modify one;
    index create idx_j_k=(j k);
    modify two;
    index create idx_j_k=(j k) / unique;
run;quit;

* Test the use of an index for the other data set:
* Log should display "INFO: Index idx_j_k selected for WHERE clause optimization.";
options msglevel=i;
data _null_;
    set two(where=(j<100));
run;

* Merge the data sets with proc sql - no index is used;
proc sql;
    create table onetwo as
    select
        one.*,
        two.x
    from one, two
    where
        one.j=two.j and
        one.k=two.k;
quit;
4

1 に答える 1

6

リンゴとオレンジを比べているかもしれません。で行う結合の場合proc sql、観測はすでに j と k で順序付けられており、インデックスを使用するよりも「マージ」を行うための高速な方法があるため、インデックスは役に立たない場合があります。

data _null_一方、ステップで行うサブセット化については、インデックス オンjが確実に役立ちます。で同じサブセット化を行うと、インデックスproc sql使用されていることがわかります。

proc sql;
  select * from two where j < 100;
quit;
/* on log
INFO: Index idx_j_k selected for WHERE clause optimization.
*/

ところで、文書化されていないオプションを使用して、クエリがどのように実行_methodされるかを調べることができます。proc sql私の Windows 上の sas 9.2 では、「ハッシュ結合」と呼ばれるものを実行していると報告されます。

proc sql _method;
  create table onetwo as
  select
    one.*,
    two.x
  from one, two
  where
    one.j=two.j and
    one.k=two.k;
quit;

/* on log
NOTE: SQL execution methods chosen are:

  sqxcrta
      sqxjhsh
          sqxsrc( WORK.ONE )
          sqxsrc( WORK.TWO )
*/

詳細については、Paul Kent のTech noteを参照してください。

于 2009-10-12T14:08:24.680 に答える