Oracle简单选择查询优化

时间:2013-07-31 20:19:01

标签: oracle select optimization

我有以下简单的动态选择查询

Select RELATIONSHIP 
  from DIME_MASTER 
 WHERE CIN=? AND SSN=? AND ACCOUNT_NUMBER=?

该表有1,083,701条记录。该查询执行需要11到12秒,这是昂贵的。 DIME_MASTER表有ACCOUNT,CARD_NUMBER INDEXES。请帮助我优化此查询,以便查询执行时间小于秒。

2 个答案:

答案 0 :(得分:1)

查看谓词信息:

--------------------------------------
 1 - filter(TO_NUMBER("DIME_MASTER"."SSN")=226550956 
            AND TO_NUMBER("DIME_MASTER"."ACCOUNT_NUMBER")=4425050005218650 
            AND TO_NUMBER("DIME_MASTER"."CIN")=00335093464) 

列的类型为NVARCHAR,但查询中的参数为NUMBER Oracle必须将数字转换为字符串,但有时在转换时不是很聪明。
神谕和算命者并不总是正确的;)

这些强制转换会阻止查询使用索引。

使用显式转换重写查询:

Select RELATIONSHIP 
  from DIME_MASTER 
 WHERE CIN=to_char(?) AND SSN=to_char(?) AND ACCOUNT_NUMBER=to_char(?)

然后运行此命令:

exec dbms_stats.gather_table_stats( user, 'DIME_MASTER' );

并运行查询并向我们显示新的解释计划。

请你不要在这里粘贴解释计划,它们是不可读的,
请改用pastebin,并在此处仅粘贴链接,谢谢。

看看这个简单的例子,它说明了为什么需要显式的强制转换:

CREATE TABLE "DIME_MASTER" ( 
  "ACCOUNT_NUMBER" NVARCHAR2(16)
);
insert into dime_master
select round( dbms_random.value( 1, 100000 )) from dual
connect by level <= 100000;
commit;
create index dime_master_acc_ix on dime_master( account_number );

explain plan for select * from dime_master
where account_number = 123;

select * from table( dbms_xplan.display );

Plan hash value: 1551952897

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

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

   1 - filter(TO_NUMBER("ACCOUNT_NUMBER")=123)




explain plan for select * from dime_master
where account_number = to_char( 123 );

select * from table( dbms_xplan.display );
Plan hash value: 3367829596

---------------------------------------------------------------------------------------
| Id  | Operation        | Name               | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |                    |     3 |    54 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| DIME_MASTER_ACC_IX |     3 |    54 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------

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

   1 - access("ACCOUNT_NUMBER"=U'123')

答案 1 :(得分:0)

根据列的基数(总行数/唯一值) - 您可以在每列上创建位图索引。位图索引对于and / or操作非常有用。

经验法则说,位图索引对基数超过10%很有用。

create bitmap index DIME_MASTER_CIN_BIX on DIME_MASTER (CIN);