web-dev-qa-db-fra.com

valeur de hachage pour l'instruction SQL

Lorsque nous exécutons une instruction SQL dans Oracle, une valeur de hachage est affectée à cette instruction SQL et stockée dans le cache de la bibliothèque. Ainsi, plus tard, si un autre utilisateur demande la même requête, Oracle trouve la valeur de hachage et exécute le même plan d'exécution. Mais, j'ai un doute sur la valeur de hachage. Je veux dire, comment la valeur de hachage est générée? , je veux dire, si le serveur Oracle utilise des algorithmes ou s'il convertit simplement la chaîne SQL en une valeur numérique.

Depuis, je lisais Pro Oracle SQL book sur lequel il est écrit que,

select * from employees where department_id = 60;

SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID = 60;

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

retournera une valeur de hachage différente, car lorsque l'instruction SQL est exécutée, Oracle convertit d'abord la chaîne en valeur de hachage. Mais, quand j'ai essayé cela, alors il retourne la même valeur de hachage.

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)
6
Ravi

Dans le texte de votre question, vous semblez décrire le sql_id et/ou le hash_value. Il s'agit du hachage du texte de l'instruction SQL et utilisé par Oracle pour déterminer si une instruction SQL particulière existe déjà dans le pool partagé. Ce que vous montrez dans votre exemple, cependant, est le plan_hash_value, qui est le hachage du plan généré pour l'instruction SQL. Il existe potentiellement une relation plusieurs à plusieurs entre les deux. Une seule instruction SQL (sql_id/hash_value) peut avoir plusieurs plans différents (plan_hash_value) et plusieurs instructions SQL différentes peuvent partager le même plan.

Ainsi, par exemple, si j'écris deux instructions SQL différentes qui interrogent une ligne particulière de la table EMP, j'obtiendrai le même 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')

Si je regarde dans v$sql, cependant, je verrai que deux valeurs différentes sql_id et hash_value ont été générées

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 reconnaît que ces deux instructions sont des requêtes différentes avec des hachages sql_id et hash_value différents. Mais ils génèrent tous deux le même plan et se retrouvent avec le même plan_hash_value.

9
Justin Cave

définir les lignes 300 col BEGIN_INTERVAL_TIME pour a30, sélectionnez a.snap_id, a.begin_interval_time, b.plan_hash_value à partir de dba_hist_snapshot a, dba_hist_sqlstat b où a.snap_id = b.snap_id = b.snl_id et b.sql_id

0
Selvaraj Prakash

Je dirais que vous venez de prouver que le livre est faux dans ce cas. Et théoriquement, il semble préférable que le hachage identifie l'instruction SQL conceptuelle au lieu d'une chaîne à majuscule aléatoire ... Et j'espère que les commentaires seront également ignorés lors de la génération du hachage. ;-)

0
C.B.