Oracle数据库数据恢复、性能优化

找回密码
注册
搜索
热搜: 活动 交友 discuz
发新帖

84

积分

1

好友

27

主题
1#
发表于 2013-1-13 22:13:56 | 查看: 4403| 回复: 5
  在sql优化的过程中看到同事这样写SQL:t1.a || t1.b || t1.c = t2.a || t2.b || t2.c这样导致了不走索引,sql语句的性能很差。
我在自己机器上测试下,想写个文档,以此来给开发的同事上一课,没想到实验失败。想请网友们帮我看看...可能是一时晕了。不知道原因在哪儿?为什么两条语句执行计划一样?
实验过程:
现象:如果表t1和t2 字段a,b 上有索引 这种写法t1.a || t1.b || t1.c = t2.a || t2.b || t2.c 是不会走索引的。应该写成t1.a=t2.a and t1.b=t2.b 这样就会根据索引检索数据,速度就很快了。
测试:
创建表1:  create table t1 (a number,b date,c varchar2(10));
插入测试数据:
declare
  na  integer;
  nc  varchar2(10) :='test1';
begin
   for na in  1..10000 loop
insert into t1 (a,b,c) values (na,sysdate+na,nc);
end loop;
commit;
end;
创建表2:create table t2 as select * from t1;
为了测试方便删除一部分数据,使查询的时候走索引:
SQL> delete from t2 where rownum<9990;; --保留10行相同数据
Commit;
向T2插入更多不同数据:
declare
  na  integer;
  nc  varchar2(10) :='test1';
begin
   for na in  10001..20000 loop
insert into t2 (a,b,c) values (na,sysdate-na,nc);
end loop;
commit;
end;
为两张1000数据的表创建唯一索引:
create unique index inx_t1_a on t1 (a);
create unique index inx_t2_a on t2 (a);
分析表
SQL> execute dbms_stats.gather_table_stats(USER,'T1',CASCADE=>TRUE);

PL/SQL procedure successfully completed

SQL> execute dbms_stats.gather_table_stats(USER,'T2',CASCADE=>TRUE);

PL/SQL procedure successfully completed

分别查看这两条语句的执行情况:
select t1.b,t2.c from t1,t2 where t1.a||t1.b=t2.a||t2.b;
select t1.b,t2.c from t1,t2 where t1.a=t2.a and t2.b=t1.b;
SQL> set autotrace on
SQL> set timing on
SQL> select t1.b,t2.c from t1,t2 where t1.a||t1.b=t2.a||t2.b;

B          C
--------- ----------
04-OCT-39 test1
05-OCT-39 test1
06-OCT-39 test1
07-OCT-39 test1
08-OCT-39 test1
09-OCT-39 test1
10-OCT-39 test1
11-OCT-39 test1
12-OCT-39 test1
13-OCT-39 test1
14-OCT-39 test1

11 rows selected.

Elapsed: 00:00:00.04

Execution Plan
----------------------------------------------------------
Plan hash value: 1838229974

---------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time          |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |          |  1001K|    29M|    27  (15)| 00:00:01 |
|*  1 |  HASH JOIN           |          |  1001K|    29M|    27  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   | 10000 |   117K|    11   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   | 10011 |   185K|    12   (0)| 00:00:01 |
---------------------------------------------------------------------------

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

   1 - access(TO_CHAR("T1"."A")||INTERNAL_FUNCTION("T1"."B")=TO_CHAR("T2
              "."A")||INTERNAL_FUNCTION("T2"."B"))


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         77  consistent gets
          0  physical reads
          0  redo size
        775  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         11  rows processed

SQL> select t1.b,t2.c from t1,t2 where t1.a=t2.a and t2.b=t1.b;

B          C
--------- ----------
04-OCT-39 test1
05-OCT-39 test1
06-OCT-39 test1
07-OCT-39 test1
08-OCT-39 test1
09-OCT-39 test1
10-OCT-39 test1
11-OCT-39 test1
12-OCT-39 test1
13-OCT-39 test1
14-OCT-39 test1

11 rows selected.

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 1838229974

---------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time          |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |          | 10000 |   302K|    24   (5)| 00:00:01 |
|*  1 |  HASH JOIN           |          | 10000 |   302K|    24   (5)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T1   | 10000 |   117K|    11   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T2   | 10011 |   185K|    12   (0)| 00:00:01 |
---------------------------------------------------------------------------

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

   1 - access("T1"."A"="T2"."A" AND "T2"."B"="T1"."B")


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         77  consistent gets
          0  physical reads
          0  redo size
        775  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         11  rows processed

2#
发表于 2013-1-14 09:30:05
select t1.b,t2.c from t1,t2 where t1.a=t2.a and t2.b=t1.b;

==》
1.无任何谓词条件
2. 表很小

回复 只看该作者 道具 举报

3#
发表于 2013-1-14 10:17:51
多谢老大指点,加了谓词条件就行了。

回复 只看该作者 道具 举报

4#
发表于 2013-1-14 10:56:07
select t1.b,t2.c from t1,t2 where t1.a=t2.a and t2.b=t1.b;

这个SQL走HASH JOIN还是很合理的

回复 只看该作者 道具 举报

5#
发表于 2013-1-14 13:27:20
我觉得之所以走hash join 是因为两张表 都是1W条左右的数据。数据量差不多。如果是一张大表然后Join一张小表估计就要 nest loops了。
例如:select b.account,
                                                 b.en_code,
                                                 b.chinese_name,
                                                 b.account_type,
                                                 b.currence_code,
                                                 case
                                                         when s.account_status = '11' then
                                                                b.open_date
                                                         else
                                                                b.importdate
                                                 end,
                                                 b.file_number,
                                                 b.instcode,
                                                 '1',
                                                 -- b.auditdate,
                                                 b.importdate,
                                                 b.businessid,
                                                 -- b.auditname,
                                                 -- b.modifyuser,
                                                 b.iscommit,
                                                 'A',
                                                 '',
                                                 b.branch_code,
                                                 b.branch_name,
                                                 s.account_status,
                                                 b.amtype,
                                                 b.account_cata,
                                                 b.limit_type,
                                                 b.remark,
                                                 b.is_handiwork,
                                                 b.account_limit
                                from tmp_t_base_account b
                                ,tmp_account_status s
                         where b.account || b.instcode || b.currence_code = s.account_num
                                 and s.account_status in ('11', '12')



ID PID Estim
Card Actual
Rows Row Source Operation BG
Consistent
Read Mode
(cr) OS
Buffer
Gets
(pr) OS
Write
Calls
(pw) Time
(secs) Obj Cost Estim
Size
(bytes)
1: 0 101 751 NESTED LOOPS  847142964 699 0 1193.496 0 108 20705
2: 1 128 414043  TABLE ACCESS FULL TMP_T_BASE_ACCOUNT 10833 692 0 4.077 17081 3 22656
3: 1 1 751  TABLE ACCESS FULL TMP_ACCOUNT_STATUS 847132131 7 0 2374.070 17056 1 28

回复 只看该作者 道具 举报

6#
发表于 2013-1-14 13:32:26
和你的where 条件、 select出来的表达式都有关系
  1. SQL> select t1.b,t2.c from t1,t2 where t1.a=t2.a and t2.b=t1.b;

  2. 11 rows selected.


  3. Execution Plan
  4. ----------------------------------------------------------
  5. Plan hash value: 1838229974

  6. ---------------------------------------------------------------------------
  7. | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
  8. ---------------------------------------------------------------------------
  9. |   0 | SELECT STATEMENT   |      | 10000 |   302K|    24   (0)| 00:00:01 |
  10. |*  1 |  HASH JOIN         |      | 10000 |   302K|    24   (0)| 00:00:01 |
  11. |   2 |   TABLE ACCESS FULL| T1   | 10000 |   117K|    12   (0)| 00:00:01 |
  12. |   3 |   TABLE ACCESS FULL| T2   | 10011 |   185K|    12   (0)| 00:00:01 |
  13. ---------------------------------------------------------------------------

  14. Predicate Information (identified by operation id):
  15. ---------------------------------------------------

  16.    1 - access("T1"."A"="T2"."A" AND "T2"."B"="T1"."B")


  17. Statistics
  18. ----------------------------------------------------------
  19.           2  recursive calls
  20.           0  db block gets
  21.          83  consistent gets
  22.           0  physical reads
  23.           0  redo size
  24.         791  bytes sent via SQL*Net to client
  25.         543  bytes received via SQL*Net from client
  26.           2  SQL*Net roundtrips to/from client
  27.           0  sorts (memory)
  28.           0  sorts (disk)
  29.          11  rows processed

  30. SQL> select t1.b,t2.c from t1,t2 where t1.a=t2.a ;

  31. 11 rows selected.


  32. Execution Plan
  33. ----------------------------------------------------------
  34. Plan hash value: 2959412835

  35. ---------------------------------------------------------------------------
  36. | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
  37. ---------------------------------------------------------------------------
  38. |   0 | SELECT STATEMENT   |      | 10000 |   224K|    24   (0)| 00:00:01 |
  39. |*  1 |  HASH JOIN         |      | 10000 |   224K|    24   (0)| 00:00:01 |
  40. |   2 |   TABLE ACCESS FULL| T2   | 10011 |   107K|    12   (0)| 00:00:01 |
  41. |   3 |   TABLE ACCESS FULL| T1   | 10000 |   117K|    12   (0)| 00:00:01 |
  42. ---------------------------------------------------------------------------

  43. Predicate Information (identified by operation id):
  44. ---------------------------------------------------

  45.    1 - access("T1"."A"="T2"."A")


  46. Statistics
  47. ----------------------------------------------------------
  48.           1  recursive calls
  49.           0  db block gets
  50.          80  consistent gets
  51.           0  physical reads
  52.           0  redo size
  53.         791  bytes sent via SQL*Net to client
  54.         543  bytes received via SQL*Net from client
  55.           2  SQL*Net roundtrips to/from client
  56.           0  sorts (memory)
  57.           0  sorts (disk)
  58.          11  rows processed
  59.                  
  60.                  
  61.                  
  62.                  

  63. SQL> select 1 from t1,t2 where t1.a=t2.a;

  64. 11 rows selected.


  65. Execution Plan
  66. ----------------------------------------------------------
  67. Plan hash value: 1184619912

  68. ----------------------------------------------------------------------------------
  69. | Id  | Operation             | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
  70. ----------------------------------------------------------------------------------
  71. |   0 | SELECT STATEMENT      |          | 10000 | 90000 |     8  (13)| 00:00:01 |
  72. |   1 |  NESTED LOOPS         |          | 10000 | 90000 |     8  (13)| 00:00:01 |
  73. |   2 |   INDEX FAST FULL SCAN| INX_T1_A | 10000 | 40000 |     7   (0)| 00:00:01 |
  74. |*  3 |   INDEX UNIQUE SCAN   | INX_T2_A |     1 |     5 |     0   (0)| 00:00:01 |
  75. ----------------------------------------------------------------------------------

  76. Predicate Information (identified by operation id):
  77. ---------------------------------------------------

  78.    3 - access("T1"."A"="T2"."A")


  79. Statistics
  80. ----------------------------------------------------------
  81.           1  recursive calls
  82.           0  db block gets
  83.          37  consistent gets
  84.           0  physical reads
  85.           0  redo size
  86.         634  bytes sent via SQL*Net to client
  87.         543  bytes received via SQL*Net from client
  88.           2  SQL*Net roundtrips to/from client
  89.           0  sorts (memory)
  90.           0  sorts (disk)
  91.          11  rows processed
复制代码

回复 只看该作者 道具 举报

您需要登录后才可以回帖 登录 | 注册

QQ|手机版|Archiver|Oracle数据库数据恢复、性能优化

GMT+8, 2024-11-16 07:51 , Processed in 0.052658 second(s), 20 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部
TEL/電話+86 13764045638
Email service@parnassusdata.com
QQ 47079569