我有以下简单的动态选择查询
Select RELATIONSHIP
from DIME_MASTER
WHERE CIN=? AND SSN=? AND ACCOUNT_NUMBER=?
该表有 1,083,701 条记录。此查询需要 11 到 12 秒才能执行,这很昂贵。DIME_MASTER 表有 ACCOUNT、CARD_NUMBER INDEXES。请帮助我优化此查询,以使查询执行时间低于秒。
我有以下简单的动态选择查询
Select RELATIONSHIP
from DIME_MASTER
WHERE CIN=? AND SSN=? AND ACCOUNT_NUMBER=?
该表有 1,083,701 条记录。此查询需要 11 到 12 秒才能执行,这很昂贵。DIME_MASTER 表有 ACCOUNT、CARD_NUMBER INDEXES。请帮助我优化此查询,以使查询执行时间低于秒。
查看谓词信息:
--------------------------------------
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')
根据列的基数(总行数/唯一值) - 您可以在每列上创建位图索引。位图索引对于and
/or
操作非常有用。
经验法则说位图索引对于大于 10% 的基数很有用。
create bitmap index DIME_MASTER_CIN_BIX on DIME_MASTER (CIN);