2

全て

  1. SQL where 句の列の順序に関する効率的な問題はありますか? Web を検索したところ、最初に結合、次に他のフィルターであるという提案が見つかりました。例えば、

    select t1.a, t2.b 
    from table1 t1, table2 t2 
    where t1.a = t2.a and t1 > 1 and t2 > 2;
    

t1 > 1の前に着替えたら何か質問はありますt1.a = t2.aか?

  1. exists 句の列の順序を知りたいです。例えば、

    select t1.a, t2.b 
    from table1, table2 t2 
    where t1.a = t2.a 
      and not exists (select 1 from table3 t3 where t1.a = t3.a and t1.b = t3.b)
    

に変えたら何か効果あるのかt1.b = t3.bt3.b = t1.b?列の順序は重要ですか?

  1. 誰でもSQL選択実行ステップを説明し、便利なチュートリアルリンクを提供できますか?
4

4 に答える 4

2

WHERE 句の述語の順序はパフォーマンスに影響しないと言う人々は、ほとんどの場合正しいです。ただし、オプティマイザーが統計から把握できるよりも、システム内のデータ、特にその分布と偏りについて多くのことを知っていることは依然としてあります。このような状況では、オプティマイザに可能な限り最良の情報を提供することが重要です。

これは、先週遭遇した実際の状況から抜粋した例です (今はテスト ケースを実行する時間がありませんが、後で実行します)。

状況: 3 つのテーブル、親と 2 つの子。タスクは、子の一意でない行を検索して、親の一意の行を選択することです。すべてのテーブルには何百万もの行があります。

私の最初の試みは次のようなものでした:

select parent.*
from   child1
       , child2
       , parent
where child1.col_a = 'whatever'
and child2.col_n = 9999
and child1.parent_id = child2.parent_id
and parent.id = child2.parent_id

クエリは正しい結果セットを返しましたが、パフォーマンスはかなり悪かったです。EXPLAIN PLAN は、クエリが CHILD2 を駆動していることを示していました。CHILD1 のフィルタはより選択的だったため、これは誤りでした。そこで、クエリを次のように書き直しました。

select parent.*
from   child1
       , child2
       , parent
where child1.col_a = 'whatever'
and child2.col_n = 9999
and child2.parent_id = child1.parent_id
and parent.id = child1.parent_id

これで、クエリによって CHILD1 が追い出され、パフォーマンスが 1 桁以上向上しました。これは常に発生するわけではありませんが、WHERE 句をいじることは依然として有効なチューニング手法です。

CBO は非常にスマートなソフトウェアです。とは言っても、私たちはただごちゃごちゃした WHERE 句をそれに放り込んで、毎回最良の Explain Plan を生成することを期待することはできません。クエリが複雑になるほど (複雑さは結合の数によって定義されます)、意味のある方法で WHERE 句を編成することがより重要になります。それは何の害もありません。


ところで、ANSI 結合構文はパフォーマンスに再び影響を与えないと言っている人々は、ほとんどの場合正しいだけです。場合によっては、オプティマイザーが劣った実行計画を作成するようになります。 詳細をご覧ください

于 2013-01-23T09:23:10.867 に答える
2

これを取り除くには、JOIN代わりにキーワードを使用して明示的な ANSI SQL-92 構文を使用します。

select t1.a, t2.b 
from table1 t1
inner join table2 t2 on t1.a = t2.a
where  t1 > 1 and t2 > 2;

これにより、句に結合条件がなくなり、条件WHEREを簡単に追加できます。

2 番目のクエリでは、次のように使用できますOUTER JOIN

select t1.a, t2.b 
from table1
inner join table2 t2 on t1.a = t2.a
LEFT JOIN table3 t3 on t1.a = t3.a and t1.b = t3.b
where t3.a IS NULL;

これがあなたの質問に答えていないことはわかっていますが、この古い結合構文は、where 句の条件がすべて曖昧であるという問題です。推奨されていないため、回避するようにしてください。

于 2013-01-23T07:54:52.283 に答える
0

where 句の順序は重要ではありません。ANSI JOIN 構文は読みやすさを向上させますが、パフォーマンスには影響しません。ポイントを証明するには:

create table t1 (a number, x number);
create table t2 (a number, b number);
insert into t1 (a, x) select level, mod(level,100) from dual connect by level <= 100000;
insert into t2 (a, b) select level, mod(level,10)  from dual connect by level <= 100000;
exec dbms_stats.gather_table_stats(user,'t1');
exec dbms_stats.gather_table_stats(user,'t2');
set autotrace trace explain

4 つのクエリすべて

select t1.a, t2.b from t1, t2 where t1.a=t2.b and t1.x > 5 and t2.b > 5;
select t1.a, t2.b from t1, t2 where t1.a=t2.b and t2.b > 5 and t1.x > 5;
select t1.a, t2.b from t1, t2 where t1.x > 5 and t2.b > 5 and t1.a=t2.b;
select t1.a, t2.b from t1 join t2 on t1.a=t2.b where t1.x > 5 and t2.b > 5;

まったく同じクエリプランを生成する

Plan hash value: 282751716
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      | 44444 |   434K|    88   (7)| 00:00:02 |
|*  1 |  HASH JOIN         |      | 44444 |   434K|    88   (7)| 00:00:02 |
|*  2 |   TABLE ACCESS FULL| T2   | 44444 |   130K|    42   (5)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| T1   | 94946 |   649K|    44   (5)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("T1"."A"="T2"."B")
   2 - filter("T2"."B">5)
   3 - filter("T1"."X">5 AND "T1"."A">5)
于 2013-01-23T08:17:18.590 に答える
0

コスト ベース オプティマイザー (CBO) の下での where 句の述語の順序は重要ではありません。CBO は適切と思われるように述語を喜んで再配置するためです (オラクルにそうしないように指示するヒントをそこに貼り付けていない限り)。これ)。

述語の順序付けに注意を払う必要があるルールベースのオプティマイザーの場合はそうでしたが、まだ RBO を使用している非常に古いバージョンの Oracle を使用していないことを願っています。

于 2013-01-23T08:01:56.747 に答える