8

Oracle で sql ステートメントを実行すると、その sql ステートメントにハッシュ値が割り当てられ、ライブラリ キャッシュに格納されます。そのため、後で別のユーザーが同じクエリを要求した場合、Oracle はハッシュ値を見つけて同じ実行計画を実行します。しかし、ハッシュ値について1つ疑問があります。つまり、ハッシュ値はどのように生成されるのでしょうか? 、つまり、Oracleサーバーが何らかのアルゴリズムを使用するか、SQL文字列を数値に変換するだけか.

以来、Pro Oracle SQLの本を読んでいました。

select * from employees where department_id = 60;

SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID = 60;

select /* a_comment */ * from employees where department_id = 60;

SQLステートメントが実行されると、Oracleは最初に文字列をハッシュ値に変換するため、異なるハッシュ値が返されます。しかし、これを試してみると、同じハッシュ値が返されます。

SQL> select * from boats where bid=10;

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 2799518614

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |     1 |    16 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| BOATS |     1 |    16 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | B_PK  |     1 |       |     0   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

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

   2 - access("BID"=10)

SQL> SELECT * FROM BOATS WHERE BID=10;

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 2799518614

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |     1 |    16 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| BOATS |     1 |    16 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | B_PK  |     1 |       |     0   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

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

   2 - access("BID"=10)
4

3 に答える 3

10

質問のテキストでは、sql_idおよび/またはについて説明しているようhash_valueです。これは SQL ステートメントのテキストのハッシュであり、特定の SQL ステートメントが共有プールに既に存在するかどうかを判断するために Oracle が使用するものです。ただし、例で示しているのplan_hash_valueは、SQL ステートメント用に生成された計画のハッシュです。潜在的に、2 つの間に多対多の関係があります。1 つの SQL ステートメント ( sql_id/ hash_value) に複数の異なるプラン ( plan_hash_value) を含めることができ、複数の異なる SQL ステートメントで同じプランを共有できます。

したがって、たとえば、EMPテーブルの特定の行をクエリする 2 つの異なる SQL ステートメントを記述した場合、同じ結果が得られますplan_hash_value

SQL> set autotrace traceonly;
SQL> select * from emp where ename = 'BOB';

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    39 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |    39 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

   1 - filter("ENAME"='BOB')


SQL> ed
Wrote file afiedt.buf

  1* select * FROM emp WHERE ename = 'BOB'
SQL> /

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    39 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |    39 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

   1 - filter("ENAME"='BOB')

ただし、 を調べると、2 つの異なると の値が生成されv$sqlていることがわかりますsql_idhash_value

SQL> set autotrace off;
SQL> ed
Wrote file afiedt.buf

  1  select sql_id, sql_text, hash_value, plan_hash_value
  2    from v$sql
  3   where sql_text like 'select%BOB%'
  4*    and length(sql_text) < 50
SQL> /

SQL_ID        SQL_TEXT                                 HASH_VALUE PLAN_HASH_VALUE
------------- ---------------------------------------- ---------- ---------------
161v96c0v9c0n select * FROM emp WHERE ename = 'BOB'      28618772      3956160932
cvs1krtgzfr78 select * from emp where ename = 'BOB'    1610046696      3956160932

Oracle は、これら 2 つのステートメントが異なるハッシュsql_idを持つ異なるクエリであることを認識しています。hash_valueしかし、どちらもたまたま同じプランを生成するため、最終的には同じplan_hash_value.

于 2013-04-15T09:51:48.563 に答える
0

行 300 を設定 a30 の列 BEGIN_INTERVAL_TIME dba_hist_snapshot a、dba_hist_sqlstat b から a.snap_id、a.begin_interval_time、b.plan_hash_value を選択 a.snap_id=b.snap_id および b.sql_id='&sql_id' の順序で 1;

于 2015-10-15T01:42:23.467 に答える