Oracle简单选择查询优化

Oracle简单选择查询优化,oracle,select,optimization,Oracle,Select,Optimization,下面是一个简单的动态选择查询 Select RELATIONSHIP from DIME_MASTER WHERE CIN=? AND SSN=? AND ACCOUNT_NUMBER=? 该表有1083701条记录。执行此查询需要11到12秒,这非常昂贵。DIME_主表具有帐户、卡号索引。请帮助我优化此查询,使查询执行时间不到几分之一秒 根据列的基数(总行/唯一值)-可以在每列上创建位图索引。位图索引对于和/或操作非常有用 根据经验,位图索引对于基数大于10%的情况非常有用 cre

下面是一个简单的动态选择查询

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

该表有1083701条记录。执行此查询需要11到12秒,这非常昂贵。DIME_主表具有帐户、卡号索引。请帮助我优化此查询,使查询执行时间不到几分之一秒

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

根据经验,位图索引对于基数大于10%的情况非常有用

create bitmap index DIME_MASTER_CIN_BIX on DIME_MASTER (CIN);

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

根据经验,位图索引对于基数大于10%的情况非常有用

create bitmap index DIME_MASTER_CIN_BIX on DIME_MASTER (CIN);

查看谓词信息:

--------------------------------------
 1 - filter(TO_NUMBER("DIME_MASTER"."SSN")=226550956 
            AND TO_NUMBER("DIME_MASTER"."ACCOUNT_NUMBER")=4425050005218650 
            AND TO_NUMBER("DIME_MASTER"."CIN")=00335093464) 
列的类型是NVARCHAR,但查询中的参数是数字。
甲骨文必须将数字转换成字符串,但有时它在转换方面不是很聪明。
预言家和算命师并不总是对的;)

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

使用显式转换将查询重写为:

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' );
然后运行查询并向我们显示新的解释计划。

请不要在这里粘贴解释计划,它们无法阅读,
请改用,并仅在此处粘贴链接,谢谢。

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

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')
创建表“DIME_MASTER”(
“账号”NVARCHAR2(16)
);
插入dime_母版
从dual中选择round(dbms_random.value(11000))

按级别连接查看谓词信息:

--------------------------------------
 1 - filter(TO_NUMBER("DIME_MASTER"."SSN")=226550956 
            AND TO_NUMBER("DIME_MASTER"."ACCOUNT_NUMBER")=4425050005218650 
            AND TO_NUMBER("DIME_MASTER"."CIN")=00335093464) 
列的类型是NVARCHAR,但查询中的参数是数字。
甲骨文必须将数字转换成字符串,但有时它在转换方面不是很聪明。
预言家和算命师并不总是对的;)

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

使用显式转换将查询重写为:

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' );
然后运行查询并向我们显示新的解释计划。

请不要在这里粘贴解释计划,它们无法阅读,
请改用,并仅在此处粘贴链接,谢谢。

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

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')
创建表“DIME_MASTER”(
“账号”NVARCHAR2(16)
);
插入dime_母版
从dual中选择round(dbms_random.value(11000))

按级别连接好在
cin
ssn
account\u number
中的所有3个上按选择性顺序放置一个索引(列中具有最唯一值的索引应排在第一位)。如果可能,使索引唯一。。。那么动态是可怕的。。。我想你的意思是每次都要更改变量而不是构建查询。如果没有适当的索引,难怪这会很慢。。。你试了什么?执行计划显示了什么?您需要向我们显示表和索引定义,以及每个表的行数。也许您的表定义不好。可能索引没有正确创建。也许你在你认为你有的专栏上没有索引。如果看不到表和索引定义,我们无法判断。我们还需要行计数,因为这会极大地影响查询优化。如果您知道如何进行
解释
或获取执行计划,请将结果也放入问题中。当结果列表的总数较高时,查询将需要一些时间来执行。因此,确保给定的约束是否给出了如此多的结果。@Ben如果对所有列都具有相等条件,则索引中列的顺序并不重要。它是O(logn)。我们将在
cin
ssn
账号
的所有3个索引上按选择性顺序放置一个索引(列中具有最唯一值的索引应排在第一位)。如果可能,使索引唯一。。。那么动态是可怕的。。。我想你的意思是每次都要更改变量而不是构建查询。如果没有适当的索引,难怪这会很慢。。。你试了什么?执行计划显示了什么?您需要向我们显示表和索引定义,以及每个表的行数。也许您的表定义不好。可能索引没有正确创建。也许你在你认为你有的专栏上没有索引。如果看不到表和索引定义,我们无法判断。我们还需要行计数,因为这会极大地影响查询优化。如果您知道如何进行
解释
或获取执行计划,请将结果也放入问题中。当结果列表的总数较高时,查询将需要一些时间来执行。因此,确保给定的约束是否给出了如此多的结果。@Ben如果对所有列都具有相等条件,则索引中列的顺序并不重要。它是O(logn)。那么我如何在查询中使用它呢?我已经为CIN和SSN创建了两个位图索引
在DIME\U MASTER(CIN)上创建位图索引DIME\U MASTER\U CIN\U BIX;在DIME\U MASTER(SSN)上创建位图索引DIME\U MASTER\U SSN\U BIX但性能没有任何改进。查询仍然需要11.3到11.5秒。DIME_主结构
创建表“DIME”。“DIME_主结构”(“帐户号”NVARCHAR2(16)、“应用程序号”NVARCHAR2(14)、“名字”NVARCHAR2(15)、“姓氏”NVARCHAR2(25)、“SSN”NVARCHAR2(9)、“CIN”NVARCHAR2(12),“日期更新”日期,“账簿指示符”NVARCHAR2(1),“卡号”NVARCHAR2(16),“关系”NVARCHAR2(1))
---------------------------------------------------------------------------------------Id |操作|名称|行