三、表关联顺序的HINT


1、leading hint

在多表关联中,这个hint指定由哪个表作为驱动表,告诉优化器先访问哪个表的数据。


SQL> create table t1 as select 1 id,object_name name from dba_objects;


Table created.


SQL> create index ind_t1 on t1(id,name);


Index created.


SQL> exec dbms_stats.gather_table_stats(user,'t1',cascade=>true,estimate_percent=>100);


PL/SQL procedure successfully completed.


SQL> drop table t;


Table dropped.


SQL> create table t as select object_id id,object_name name from dba_objects;


Table created.


SQL> create index ind_t on t(id,name);


Index created.


SQL> exec dbms_stats.gather_table_stats(user,'t',cascade=>true,estimate_percent=>100);


PL/SQL procedure successfully completed.


要求先访问T1,再访问T


SQL> select /*+ leading(t1,t) */ t.* from t,t1 where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 1444793974


---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |    31 |   116   (5)| 00:00:02 |

|*  1 |  HASH JOIN         |      |     1 |    31 |   116   (5)| 00:00:02 |

|   2 |   TABLE ACCESS FULL| T1   | 50604 |   148K|    55   (2)| 00:00:01 |

|   3 |   TABLE ACCESS FULL| T    | 50604 |  1383K|    59   (4)| 00:00:01 |

---------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  1 - access("T1"."ID"="T"."ID")


要求先访问T,再访问T1

SQL> select /*+ leading(t,t1) */ t.*  from t,t1 where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 2914261090


-----------------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |

-----------------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |    31 |       |   249   (3)| 00:00:03 |

|*  1 |  HASH JOIN         |      |     1 |    31 |  1984K|   249   (3)| 00:00:03 |

|   2 |   TABLE ACCESS FULL| T    | 50604 |  1383K|       |    59   (4)| 00:00:01 |

|   3 |   TABLE ACCESS FULL| T1   | 50604 |   148K|       |    55   (2)| 00:00:01 |

-----------------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  1 - access("T1"."ID"="T"."ID")


为什么先访问T1的代价低?


因为T1表的ID列重复率比较高,意味着生成的哈西簇会比较少,

而hash join这个过程的代价主要是耗在生成hash簇的过程,

意味着只要哈西簇少代价就会降低;

T表的ID列重复率是很低的,生成的hash簇会比较多,此时代价自然比先访问T1要高。



结论——hash join的性能主要取决于哈西簇的生成。


2、orderd hint


告诉优化器按照from后面的顺序来选择驱动表,oracle建议用leading,比较灵活。


SQL> select /*+ ordered */ t.* from t,t1 where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 2914261090


-----------------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |

-----------------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |    31 |       |   249   (3)| 00:00:03 |

|*  1 |  HASH JOIN         |      |     1 |    31 |  1984K|   249   (3)| 00:00:03 |

|   2 |   TABLE ACCESS FULL| T    | 50604 |  1383K|       |    59   (4)| 00:00:01 |

|   3 |   TABLE ACCESS FULL| T1   | 50604 |   148K|       |    55   (2)| 00:00:01 |

-----------------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  1 - access("T1"."ID"="T"."ID")


SQL> select /*+ ordered */ t.* from t1,t where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 1444793974


---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |    31 |   116   (5)| 00:00:02 |

|*  1 |  HASH JOIN         |      |     1 |    31 |   116   (5)| 00:00:02 |

|   2 |   TABLE ACCESS FULL| T1   | 50604 |   148K|    55   (2)| 00:00:01 |

|   3 |   TABLE ACCESS FULL| T    | 50604 |  1383K|    59   (4)| 00:00:01 |

---------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  1 - access("T1"."ID"="T"."ID")





四、表关联方式的hint


/*+ use_nl(t t1) */

/*+ use_hash(t t1) */

/*+ use_merge(t t1) */


当使用很多hint的时候


SQL> select /*+ leading(t,t1) index(t1 ind_t1) index(t ind_t) use_nl(t t1) */ t.* from t,t1 where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 2389647923


----------------------------------------------------------------------------

| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |        |     1 |    31 | 50949   (1)| 00:10:12 |

|   1 |  NESTED LOOPS     |        |     1 |    31 | 50949   (1)| 00:10:12 |

|   2 |   INDEX FULL SCAN | IND_T  | 50604 |  1383K|   286   (1)| 00:00:04 |

|*  3 |   INDEX RANGE SCAN| IND_T1 |     1 |     3 |     1   (0)| 00:00:01 |

----------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  3 - access("T1"."ID"="T"."ID")


研究一下三种连接方式的sql trace


SQL> drop table t1;


Table dropped.


SQL> create table t1 as select * from t;


Table created.


SQL> create index ind_t1 on t1(id,name);


Index created.


SQL> exec dbms_stats.gather_table_stats(user,'t1',cascade=>true,estimate_percent=>100);


PL/SQL procedure successfully completed.


SQL> exec dbms_stats.gather_table_stats(user,'t',cascade=>true,estimate_percent=>100);


PL/SQL procedure successfully completed.


SQL> set autotrace off

SQL> alter session set sql_trace=true;


Session altered.


SQL> select /*+ use_nl(t1 t) */ count(1) from t1,t where t1.id=t.id;


 COUNT(1)

----------

    50604


SQL> select /*+ use_hash(t1 t) */ count(1) from t1,t where t1.id=t.id;


 COUNT(1)

----------

    50604


SQL> select /*+ use_merge(t1 t) */ count(1) from t1,t where t1.id=t.id;


 COUNT(1)

----------

    50604


SQL> alter session set sql_trace=false;


Session altered.


[oracle@oracle253 udump]$ tkprof law_ora_7171.trc law_ora_7171_text.txt


TKPROF: Release 10.2.0.4.0 - Production on Tue Aug 27 16:34:57 2013


Copyright (c) 1982, 2007, Oracle.  All rights reserved.


*******************************************************************************

count    = number of times OCI procedure was executed

cpu      = cpu time in seconds executing

elapsed  = elapsed time in seconds executing

disk     = number of physical reads of buffers from disk

query    = number of buffers gotten for consistent read

current  = number of buffers gotten in current mode (usually for update)

rows     = number of rows processed by the fetch or execute call

********************************************************************************


select /*+ use_nl(t1 t) */ count(1)

from

t1,t where t1.id=t.id



call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        2      0.22       0.23          0      51131          0           1

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total        4      0.22       0.23          0      51131          0           1


Misses in library cache during parse: 1

Optimizer mode: ALL_ROWS

Parsing user id: 57  


Rows     Row Source Operation

-------  ---------------------------------------------------

     1  SORT AGGREGATE (cr=51131 pr=0 pw=0 time=234288 us)

 50604   NESTED LOOPS  (cr=51131 pr=0 pw=0 time=253094 us)

 50604    TABLE ACCESS FULL T1 (cr=243 pr=0 pw=0 time=48 us)

 50604    INDEX RANGE SCAN IND_T (cr=50888 pr=0 pw=0 time=174963 us)(object id 52948)


********************************************************************************


select /*+ use_hash(t1 t) */ count(1)

from

t1,t where t1.id=t.id



call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        2      0.04       0.05          0        486          0           1

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total        4      0.04       0.05          0        486          0           1


Misses in library cache during parse: 1

Optimizer mode: ALL_ROWS

Parsing user id: 57  


Rows     Row Source Operation

-------  ---------------------------------------------------

     1  SORT AGGREGATE (cr=486 pr=0 pw=0 time=55377 us)

 50604   HASH JOIN  (cr=486 pr=0 pw=0 time=131253 us)

 50604    TABLE ACCESS FULL T1 (cr=243 pr=0 pw=0 time=47 us)

 50604    TABLE ACCESS FULL T (cr=243 pr=0 pw=0 time=33 us)


********************************************************************************


select /*+ use_merge(t1 t) */ count(1)

from

t1,t where t1.id=t.id



call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        2      0.16       0.17          0        486          0           1

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total        4      0.16       0.17          0        486          0           1


Misses in library cache during parse: 1

Optimizer mode: ALL_ROWS

Parsing user id: 57  


Rows     Row Source Operation

-------  ---------------------------------------------------

     1  SORT AGGREGATE (cr=486 pr=0 pw=0 time=175407 us)

 50604   MERGE JOIN  (cr=486 pr=0 pw=0 time=195280 us)

 50604    SORT JOIN (cr=243 pr=0 pw=0 time=29292 us)

 50604     TABLE ACCESS FULL T1 (cr=243 pr=0 pw=0 time=54 us)

 50604    SORT JOIN (cr=243 pr=0 pw=0 time=101547 us)

 50604     TABLE ACCESS FULL T (cr=243 pr=0 pw=0 time=48 us)


********************************************************************************


OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS


call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        4      0.00       0.00          0          0          0           0

Execute      4      0.00       0.00          0          0          0           0

Fetch        6      0.43       0.46          0      52103          0           3

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total       14      0.43       0.47          0      52103          0           3


Misses in library cache during parse: 3



OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS


call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        0      0.00       0.00          0          0          0           0

Execute      0      0.00       0.00          0          0          0           0

Fetch        0      0.00       0.00          0          0          0           0

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total        0      0.00       0.00          0          0          0           0


Misses in library cache during parse: 0


   4  user  SQL statements in session.

   0  internal SQL statements in session.

   4  SQL statements in session.

********************************************************************************


比较一致性读:

NL方式——51131

HASH方式——486

MERGE方式——486


一致性读一样但是执行计划不一样


SQL> set autotrace trace exp

SQL> select /*+ use_hash(t1 t) */ count(1) from t1,t where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 949044725


----------------------------------------------------------------------------

| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------

|   0 | SELECT STATEMENT    |      |     1 |    10 |   119   (5)| 00:00:02 |

|   1 |  SORT AGGREGATE     |      |     1 |    10 |            |          |

|*  2 |   HASH JOIN         |      | 50604 |   494K|   119   (5)| 00:00:02 |

|   3 |    TABLE ACCESS FULL| T1   | 50604 |   247K|    58   (2)| 00:00:01 |

|   4 |    TABLE ACCESS FULL| T    | 50604 |   247K|    58   (2)| 00:00:01 |

----------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  2 - access("T1"."ID"="T"."ID")


SQL> select /*+ use_merge(t1 t) */ count(1) from t1,t where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 712353386


-------------------------------------------------------------------------------------

| Id  | Operation            | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |

-------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT     |      |     1 |    10 |       |   442   (4)| 00:00:06 |

|   1 |  SORT AGGREGATE      |      |     1 |    10 |       |            |          |

|   2 |   MERGE JOIN         |      | 50604 |   494K|       |   442   (4)| 00:00:06 |

|   3 |    SORT JOIN         |      | 50604 |   247K|  1208K|   221   (4)| 00:00:03 |

|   4 |     TABLE ACCESS FULL| T1   | 50604 |   247K|       |    58   (2)| 00:00:01 |

|*  5 |    SORT JOIN         |      | 50604 |   247K|  1208K|   221   (4)| 00:00:03 |

|   6 |     TABLE ACCESS FULL| T    | 50604 |   247K|       |    58   (2)| 00:00:01 |

-------------------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  5 - access("T1"."ID"="T"."ID")

      filter("T1"."ID"="T"."ID")


选择cost较小的hash join方式。


结论:大表间的访问,HASH方式性能更高,NL最差,当驱动表是小表的时候,NL的性能才会体现出来。


改造表,将T表变为小表

SQL> truncate table t;


Table truncated.


SQL> insert into t select object_id,object_name from dba_objects where rownum<10;


9 rows created.


SQL> commit;


Commit complete.


SQL> exec dbms_stats.gather_table_stats(user,'t',cascade=>true,estimate_percent=>100);


PL/SQL procedure successfully completed.


SQL> select count(1) from t1,t where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 2183851067


-----------------------------------------------------------------------------

| Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |

-----------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |        |     1 |     8 |    10   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE    |        |     1 |     8 |            |          |

|   2 |   NESTED LOOPS     |        |     9 |    72 |    10   (0)| 00:00:01 |

|   3 |    INDEX FULL SCAN | IND_T  |     9 |    27 |     1   (0)| 00:00:01 |

|*  4 |    INDEX RANGE SCAN| IND_T1 |     1 |     5 |     1   (0)| 00:00:01 |

-----------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  4 - access("T1"."ID"="T"."ID")


强制hash join

SQL> select /*+ use_hash(t1 t) */ count(1) from t1,t where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 596805104


-----------------------------------------------------------------------------

| Id  | Operation           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |

-----------------------------------------------------------------------------

|   0 | SELECT STATEMENT    |       |     1 |     8 |    61   (5)| 00:00:01 |

|   1 |  SORT AGGREGATE     |       |     1 |     8 |            |          |

|*  2 |   HASH JOIN         |       |     9 |    72 |    61   (5)| 00:00:01 |

|   3 |    INDEX FULL SCAN  | IND_T |     9 |    27 |     1   (0)| 00:00:01 |

|   4 |    TABLE ACCESS FULL| T1    | 50604 |   247K|    58   (2)| 00:00:01 |

-----------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  2 - access("T1"."ID"="T"."ID")


禁用连接方式


A 禁用使用NL,会在剩下的两种连接方式中选择次优的。


SQL> select /*+ no_use_nl(t1 t) */ count(1) from t1,t where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 596805104


-----------------------------------------------------------------------------

| Id  | Operation           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |

-----------------------------------------------------------------------------

|   0 | SELECT STATEMENT    |       |     1 |     8 |    61   (5)| 00:00:01 |

|   1 |  SORT AGGREGATE     |       |     1 |     8 |            |          |

|*  2 |   HASH JOIN         |       |     9 |    72 |    61   (5)| 00:00:01 |

|   3 |    INDEX FULL SCAN  | IND_T |     9 |    27 |     1   (0)| 00:00:01 |

|   4 |    TABLE ACCESS FULL| T1    | 50604 |   247K|    58   (2)| 00:00:01 |

-----------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  2 - access("T1"."ID"="T"."ID")


B 禁止使用hash join

/*+ no_use_hash(t1 t) */



C 禁止使用merge join

/*+ no_use_merge(t1 t) */


五、与并行相关的hint

SQL> select /*+ parallel(t1 4) parallel(t 3) */ count(1) from t1,t where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 3903087583


-----------------------------------------------------------------------------------------------------------------

| Id  | Operation               | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |

-----------------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT        |          |     1 |     8 |     5   (0)| 00:00:01 |        |      |            |

|   1 |  SORT AGGREGATE         |          |     1 |     8 |            |          |        |      |            |

|   2 |   PX COORDINATOR        |          |       |       |            |          |        |      |            |

|   3 |    PX SEND QC (RANDOM)  | :TQ10000 |     1 |     8 |            |          |  Q1,00 | P->S | QC (RAND)  |

|   4 |     SORT AGGREGATE      |          |     1 |     8 |            |          |  Q1,00 | PCWP |            |

|   5 |      NESTED LOOPS       |          |     9 |    72 |     5   (0)| 00:00:01 |  Q1,00 | PCWP |            |

|   6 |       PX BLOCK ITERATOR |          |       |       |            |          |  Q1,00 | PCWC |            |

|   7 |        TABLE ACCESS FULL| T        |     9 |    27 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |

|*  8 |       INDEX RANGE SCAN  | IND_T1   |     1 |     5 |     1   (0)| 00:00:01 |  Q1,00 | PCWP |            |

-----------------------------------------------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  8 - access("T1"."ID"="T"."ID")


PX出现表示用了并行的方式。



SQL> conn /as sysdba

Connected.

SQL> select table_name,degree from dba_tables where owner='SCOTT' and table_name like 'T%';


TABLE_NAME       DEGREE

------------------------------------------------------------------------------

T                1

T1               1


默认的并行度


SQL> conn scott/scott

Connected.

SQL> alter table t parallel 3;


Table altered.


SQL> alter table t1 parallel 4;


Table altered.


SQL> select table_name,degree from dba_tables where owner='SCOTT' and table_name like 'T%';


TABLE_NAME       DEGREE

------------------------------------------------------------------------------

T                3

T1               4


SQL> select count(1) from t1,t where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 3903087583


-----------------------------------------------------------------------------------------------------------------

| Id  | Operation               | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |

-----------------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT        |          |     1 |     8 |     5   (0)| 00:00:01 |        |      |            |

|   1 |  SORT AGGREGATE         |          |     1 |     8 |            |          |        |      |            |

|   2 |   PX COORDINATOR        |          |       |       |            |          |        |      |            |

|   3 |    PX SEND QC (RANDOM)  | :TQ10000 |     1 |     8 |            |          |  Q1,00 | P->S | QC (RAND)  |

|   4 |     SORT AGGREGATE      |          |     1 |     8 |            |          |  Q1,00 | PCWP |            |

|   5 |      NESTED LOOPS       |          |     9 |    72 |     5   (0)| 00:00:01 |  Q1,00 | PCWP |            |

|   6 |       PX BLOCK ITERATOR |          |       |       |            |          |  Q1,00 | PCWC |            |

|   7 |        TABLE ACCESS FULL| T        |     9 |    27 |     2   (0)| 00:00:01 |  Q1,00 | PCWP |            |

|*  8 |       INDEX RANGE SCAN  | IND_T1   |     1 |     5 |     1   (0)| 00:00:01 |  Q1,00 | PCWP |            |

-----------------------------------------------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  8 - access("T1"."ID"="T"."ID")


禁止并行

SQL> select /*+ no_parallel(t1) no_parallel(t) */ count(1) from t1,t where t1.id=t.id;


Execution Plan

----------------------------------------------------------

Plan hash value: 2183851067


-----------------------------------------------------------------------------

| Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |

-----------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |        |     1 |     8 |    10   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE    |        |     1 |     8 |            |          |

|   2 |   NESTED LOOPS     |        |     9 |    72 |    10   (0)| 00:00:01 |

|   3 |    INDEX FULL SCAN | IND_T  |     9 |    27 |     1   (0)| 00:00:01 |

|*  4 |    INDEX RANGE SCAN| IND_T1 |     1 |     5 |     1   (0)| 00:00:01 |

-----------------------------------------------------------------------------


Predicate Information (identified by operation id):

---------------------------------------------------


  4 - access("T1"."ID"="T"."ID")


六、动态采样

/*+ dynamic_sampling(t 4) */



七、其他的






cache hint

在全表扫描的操作中,如果使用这个提示,oracle会将扫到的数据块放在LRU链表最被使用端,

这样的话,数据块可以长时间驻留内存。


场合:如果一个经常被访问的小表,这个设置可以提高查询的性能。


SQL> select /*+ full(emp) cache(emp) */ * from emp;


Execution Plan

----------------------------------------------------------

Plan hash value: 3956160932


--------------------------------------------------------------------------

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |      |    14 |  1218 |     3   (0)| 00:00:01 |

|   1 |  TABLE ACCESS FULL| EMP  |    14 |  1218 |     3   (0)| 00:00:01 |

--------------------------------------------------------------------------


Note

-----

  - dynamic sampling used for this statement


与KEEP池的区别,这个hint是好用db buffer的默认池大小,

keep池是另外的区域,长时间驻留在内存中KEEP池区域中。

区别在于在内存中的位置不一样。


相同点——效果是一样的,为了放到内存,提高缓存的命中率。