查询不使用索引 -

时间:2013-05-30 04:48:44

标签: database performance oracle sqlplus

有什么方法可以在REFERENCETYPE列上使用索引.Below是表结构和执行计划。

SQL> desc messaginginbox
 Name                                      Null?    Type
 ----------------------------------------- -------- ---------------------------
 MESSAGINGINBOXID                          NOT NULL VARCHAR2(28)
 REFERENCEID                               NOT NULL VARCHAR2(28)
 REFERENCETYPE                                      VARCHAR2(1)
 LISTINGID                                 NOT NULL VARCHAR2(28)
 CREATEDATE                                         DATE
 LASTUPDATED                               NOT NULL DATE
 UPDATEDBY                                 NOT NULL VARCHAR2(28)
 RENTERLISTINGMANAGERID                             VARCHAR2(28)
 OWNERLISTINGMANAGERID                              VARCHAR2(28)
 OCA                                       NOT NULL NUMBER(38)

SQL> create index idx_MESSAGINGIN_REFERENCE on MESSAGINGINBOX( REFERENCETYPE);
Index created.

SQL> analyze table MESSAGINGINBOX compute statistics;

Table analyzed.

SQL> select * from MESSAGINGINBOX where referencetype='B';

55 rows selected.

Execution Plan
-------------------------------------------------------------------------
| Id  | Operation         | Name           | Rows  | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                | 71354 |     9M|   873   (1)|
|*  1 |  TABLE ACCESS FULL| MESSAGINGINBOX | 71354 |     9M|   873   (1)|
-------------------------------------------------------------------------

SQL> create bitmap index idx_MESSAGINGIN_REFERENCE
     on MESSAGINGINBOX( REFERENCETYPE);

Index created.

SQL> analyze table MESSAGINGINBOX compute statistics;

Table analyzed.

SQL> select * from MESSAGINGINBOX where referencetype='B';

55 rows selected.

Execution Plan
-------------------------------------------------------------------------
| Id  | Operation         | Name           | Rows  | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                | 71354 |     9M|   873   (1)|
|*  1 |  TABLE ACCESS FULL| MESSAGINGINBOX | 71354 |     9M|   873   (1)|
-------------------------------------------------------------------------

SQL> select count(*) from MESSAGINGINBOX;

  COUNT(*)
----------
    142707

SQL> select distinct referencetype from MESSAGINGINBOX;

REFERENCETYPE
-------------
I             
B       

SQL> select count(distinct referencetype) from MESSAGINGINBOX;

COUNT(DISTINCTREFERENCETYPE)
----------------------------
                   2

2 个答案:

答案 0 :(得分:0)

一种方法是利用索引不包含整列列为NULL的条目这一事实 - 即创建一个仅对“B”记录编制索引的基于函数的索引:

CREATE INDEX just_the_Bs ON messaginginbox
  (CASE WHEN referencetype='B' THEN 'B' END);

但是,要使用索引,必须使用相同的表达式进行查询,例如:

SELECT * FROM messaginginbox
WHERE (CASE WHEN referencetype='B' THEN 'B' END) = 'B';

我希望这很可能使用索引范围扫描,然后使用rowid进行表查找,因为匹配此谓词的数据量相对较小。

另一种方法是使用提示 - 但请注意,您可能需要添加更多提示(例如USE_NL)以避免一些非常糟糕的执行计划:

SELECT /*+INDEX(messaginginbox,idx_MESSAGINGIN_REFERENCE)*/ *
FROM messaginginbox WHERE referencetype='B';

特别注意提示中的建议 - 强制CBO使用特定计划需要很多提示:http://jonathanlewis.wordpress.com/2013/05/28/how-to-hint/

答案 1 :(得分:0)

常规Btree索引应该在这里工作,您只需要确保ReferenceType列上有histogram

列数据偏斜,优化器似乎知道这一点。它正确地将非重复计数估计为2,这就是行估计几乎完全是行数除以2的原因。使用默认设置,Oracle根据数据分布以及列的使用方式创建直方图。

将已弃用的analyze table替换为dbms_stats.gather_table_stats,并确保使用所有默认选项。在收集统计信息之前,还需要在ReferenceType上运行查询过滤。默认情况下,如果未在谓词中使用该列,Oracle将不会创建直方图。

运行此查询以查看是否生成了直方图:

select owner, table_name, column_name, histogram
from all_tab_columns
where table_name= 'MESSAGINGINBOX';

直方图至少应该改善估计的基数(行),这是修复执行计划的第一步。