三星索引

三星索引概念:

第一颗星:与查询相关的索引行是相邻的,也就是where后面的等值谓词,可以匹配索引列顺序

第二颗星:索引行的顺序与查询语句需求一致,也就是order by 中的排序和索引顺序是否一致

第三颗星:索引行包含查询语句中所有的列


参考:《数据库索引设计与优化》


一、建立测试数据
SQL> create table id.cust(cno int,lname varchar(10),fname varchar(10),sex int,weight int,city varchar(10));


SQL> truncate table id.cust;

SQL> declare
i number;
begin
 
   for i in 1..1000 loop
      insert into id.cust 
      values(i, DBMS_RANDOM.STRING('u', 4), DBMS_RANDOM.STRING('u', 4),ABS(MOD(DBMS_RANDOM.RANDOM,2)),ABS(MOD(DBMS_RANDOM.RANDOM,150)),DBMS_RANDOM.STRING('u', 6)); 
     
  commit; 
  end loop; 

end;


二、三星索引测试
1、满足三星索引

--建立索引(三星)
SQL> create index id.idx_cust on id.cust(city,lname,fname,cno);

对于下面的sql,建立如上就是三星索引:
第一颗星:所有等值谓词的列,把这些做组合索引的开头的列,如下sql的where条件的city,lname开头,顺序随意。
第二颗星:order by的字段加入组合索引中 fname字段(索引自动排序)
第三颗星:将查询中剩余的列加入组合索引中 select中的cno字段(fname之前已加入过)


SQL> EXPLAIN PLAN FOR 
  2  select cno,fname
  3    from id.cust
  4   where lname = :1
  5     and city = :2
  6   order by fname;

Explained.

这样建立索引后,执行计划最优,如下:
SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3860859945

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

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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - access("CITY"=:2 AND "LNAME"=:1)

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

17 rows selected.




2、不满足三星索引

如果在where条件中,不满足第一颗星 等值谓词,那之前组合索引的顺序要更改
SQL> EXPLAIN PLAN FOR 
  2  select cno,fname
  3    from id.cust
  4   where lname between :lname1 and :lname2
  5     and city = :2
  6   order by fname;

Explained.


执行计划有filter过滤,还有order by排序操作, 不满足第一颗星和第二颗星
SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1720078986

-------------------------------------------------------------------------------
| Id  | Operation          | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |          |     1 |    34 |     3  (34)| 00:00:01 |
|   1 |  SORT ORDER BY     |          |     1 |    34 |     3  (34)| 00:00:01 |
|*  2 |   FILTER           |          |       |       |            |          |
|*  3 |    INDEX RANGE SCAN| IDX_CUST |     1 |    34 |     2   (0)| 00:00:01 |
-------------------------------------------------------------------------------


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

   2 - filter(:LNAME2>=:LNAME1)
   3 - access("CITY"=:2 AND "LNAME">=:LNAME1 AND "LNAME"<=:LNAME2)

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

20 rows selected.



修改一下组合索引,让order by的列fname放在between谓词列lname之前,才能满足第二颗星,避免排序操作
SQL> drop index id.idx_cust ;

Index dropped.

SQL> create  index id.idx_cust on id.cust(city,fname,lname,cno);

Index created.


SQL> EXPLAIN PLAN FOR 
  2  select cno,fname
  3    from id.cust
  4   where lname between :lname1 and :lname2
  5     and city = :2
  6   order by fname;

Explained.

查看执行计划,没有了order by排序操作(索引自动排序)
SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1083764640

------------------------------------------------------------------------------
| Id  | Operation         | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |          |     1 |    34 |     2   (0)| 00:00:01 |
|*  1 |  FILTER           |          |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| IDX_CUST |     1 |    34 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   1 - filter(:LNAME2>=:LNAME1)
   2 - access("CITY"=:2 AND "LNAME">=:LNAME1 AND "LNAME"<=:LNAME2)
       filter("LNAME">=:LNAME1 AND "LNAME"<=:LNAME2)

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

20 rows selected.


这里满足第三颗星,但第一 第二颗星只能二选一

避免排序   选择第二颗星
最窄索引片 选择第一颗星




扫描二维码关注公众号,回复: 1675311 查看本文章

猜你喜欢

转载自blog.csdn.net/fly43108622/article/details/80731849