高效的SQL(index range scan优化排序)

本文详细介绍了SQL中使用索引范围扫描的优化技术,包括实验表结构、执行计划、使用条件、注意事项及性能优势。通过实例展示了如何正确利用索引范围扫描提升查询效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

高效的SQL(index range scan优化排序)

 

一、     实验表

表的结构、内容、索引(Data is returned in the ascending order of index columns. Multiple rows with identical values are sorted in ascending order by rowid.)

doudou@TEST> desc range_scan

 Name                                                  Null?    Type

 ----------------------------------------------------- -------- ------------------------------------

 ID                                                             NUMBER

 NAME                                                           VARCHAR2(20)

 SUM                                                            VARCHAR2(20)

doudou@TEST> select * from range_scan;

 

        ID NAME                                     SUM

---------- ---------------------------------------- ----------------------------------------

         2 doudou+2                                 3

         3 doudou+3                                 3

         4 doudou+4                                 3

         5 doudou+5                                 4

         6 doudou+6                                 4

         7 doudou+7                                 4

         8 doudou+8                                 5

         9 doudou+9                                 5

        10 doudou+10                                6

        11 doudou+11                                6

        12 doudou+12                                6

 

11 rows selected.

doudou@TEST>  select index_name,column_name,table_name fromuser_ind_columns where table_name='RANGE_SCAN';

 

INDEX_NAME                     COLUMN_NAME                    TABLE_NAME

------------------------------ ------------------------------ ------------------------------

INDEX_RANGE_SCAN_SUM           SUM                            RANGE_SCAN

二、     开启执行计划,执行SQL

The optimizer uses a range scan when it finds one or more leading columns of an index specified in conditions优化器使用一个范围扫描当找到一个或多个列的索引指定主要在条件。)

1、例如:sum=’5’ sum>'5';sum<'5'and (sum> '4' and sum<'6')

doudou@TEST> select * from range_scan where sum='5';

 

        ID NAME                                     SUM

---------- ---------------------------------------- ----------------------------------------

         8 doudou+8                                 5

         9 doudou+9                                 5

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 3049432069

 

----------------------------------------------------------------------------------------------------

| Id  | Operation                   | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT            |                      |     2 |    74 |     2   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| RANGE_SCAN           |     2 |    74 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | INDEX_RANGE_SCAN_SUM |     2 |       |     1   (0)| 00:00:01 |

doudou@TEST> select * from range_scan where sum>'5';

 

        ID NAME                                     SUM

---------- ---------------------------------------- ----------------------------------------

        10 doudou+10                                6

        11 doudou+11                                6

        12 doudou+12                                6

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 3049432069

 

----------------------------------------------------------------------------------------------------

| Id  | Operation                   | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT            |                      |     3 |   111 |     2   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| RANGE_SCAN           |     3 |   111 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | INDEX_RANGE_SCAN_SUM |     3 |       |     1   (0)| 00:00:01 |

doudou@TEST> select * from range_scan where sum<'5';

 

        ID NAME                                     SUM

---------- ---------------------------------------- ----------------------------------------

         2 doudou+2                                 3

         3 doudou+3                                 3

         4 doudou+4                                 3

         5 doudou+5                                 4

         6 doudou+6                                 4

         7 doudou+7                                 4

 

6 rows selected.

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 3049432069

 

----------------------------------------------------------------------------------------------------

| Id  | Operation                   | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT            |                      |     6 |   222 |     2   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| RANGE_SCAN           |     6 |   222 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | INDEX_RANGE_SCAN_SUM |     6 |       |     1   (0)| 00:00:01 |

 

doudou@TEST> select * from range_scan where sum >'4'  and  sum<'6';

 

        ID NAME                                     SUM

---------- ---------------------------------------- ----------------------------------------

         8 doudou+8                                 5

         9 doudou+9                                 5

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 3049432069

 

----------------------------------------------------------------------------------------------------

| Id  | Operation                   | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT            |                      |     2 |    74 |     2   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| RANGE_SCAN           |     2 |    74 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | INDEX_RANGE_SCAN_SUM |     2 |       |     1   (0)| 00:00:01 |

----------------------------------------------------------------------------------------------------

 

2、index range scan使用通配符需注意 ‘%5’像这样,通配符在前的不走范围索引;’5%’通配符在最后的正常走范围索引

doudou@TEST> select * from range_scan where sum like '%5';

 

        ID NAME                                     SUM

---------- ---------------------------------------- ----------------------------------------

         8 doudou+8                                 5

         9 doudou+9                                 5

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 1933872984

 

--------------------------------------------------------------------------------

| Id  | Operation         | Name       | Rows  | Bytes | Cost (%CPU)| Time     |

--------------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |            |     2 |    74 |     3   (0)| 00:00:01 |

|*  1 |  TABLE ACCESS FULL| RANGE_SCAN |     2 |    74 |     3   (0)| 00:00:01 |

【使用通配符不恰当,导致不走索引(低效)

doudou@TEST> select * from range_scan where sum like '5%';

 

        ID NAME                                     SUM

---------- ---------------------------------------- ----------------------------------------

         8 doudou+8                                 5

         9 doudou+9                                 5

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 3049432069

 

----------------------------------------------------------------------------------------------------

| Id  | Operation                   | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT            |                      |     2 |    74 |     2   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| RANGE_SCAN           |     2 |    74 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | INDEX_RANGE_SCAN_SUM |     2 |       |     1   (0)| 00:00:01 |

【正确的使用通配符’5%’(高效)

 

3、当在索引列分组或排序的时候使用范围扫描,order by 索引列可以避免排序

doudou@TEST> select * from range_scan where sum='5' order by sum;

 

        ID NAME                                     SUM

---------- ---------------------------------------- ----------------------------------------

         8 doudou+8                                 5

         9 doudou+9                                 5

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 3049432069

 

----------------------------------------------------------------------------------------------------

| Id  | Operation                   | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT            |                      |     2 |    74 |     2   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| RANGE_SCAN           |     2 |    74 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | INDEX_RANGE_SCAN_SUM |     2 |       |     1   (0)| 00:00:01 |

【索引列进行了order by,索引没有进行更多的sort order by(高效)

doudou@TEST>  select * from range_scan where sum='5' order by id ;

 

        ID NAME                                     SUM

---------- ---------------------------------------- ----------------------------------------

         8 doudou+8                                 5

         9 doudou+9                                 5

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 823340891

 

----------------------------------------------------------------------------------------------------

-

 

| Id  | Operation                    | Name                 | Rows  | Bytes | Cost (%CPU)| Time

|

 

----------------------------------------------------------------------------------------------------

-

 

|   0 | SELECT STATEMENT             |                      |     2 |    74 |     3  (34)| 00:00:01

|

 

|   1 |  SORT ORDER BY               |                      |     2 |    74 |     3  (34)| 00:00:01

|

 

|   2 |   TABLE ACCESS BY INDEX ROWID| RANGE_SCAN           |     2 |    74 |     2   (0)| 00:00:01

|

 

|*  3 |    INDEX RANGE SCAN          | INDEX_RANGE_SCAN_SUM |     2 |       |     1   (0)| 00:00:01

|

 

----------------------------------------------------------------------------------------------------

【order by id,id不是索引列,这里又进行了排序,浪费了cost(低效)

 

三、     总结

1、index range scan 使用条件:(Data is returned in the ascending order of index columns. Multiple rows with identical values are sorted in ascending order by rowid.)

2、index range scan使用通配符需注意: ‘%name’不恰当使用不走索引,’name%’正确使用走索引

3、index range scan优点:group by 或order by  使用索引列这样就避免了再次sort,提高了性能

 

附表:

 

1、实验数据库环境

sys@TEST> show parameter optimizer_mode

 

NAME                                 TYPE                   VALUE

------------------------------------ ---------------------- ------------------------------

optimizer_mode                       string                 ALL_ROWS

sys@TEST> select * from v$version;

 

BANNER

----------------------------------------------------------------------------------------------------

Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod

PL/SQL Release 10.2.0.4.0 - Production

CORE    10.2.0.4.0      Production

TNS for Linux: Version 10.2.0.4.0 - Production

NLSRTL Version 10.2.0.4.0 – Production

 

2、官档

13.5.3.3.1 When the Optimizer Uses Index Range Scans

The optimizer uses a range scan when it finds one or more leading columns of an index specified in conditions, such as the following:

  • col1 = :b1
  • col1 < :b1
  • col1 > :b1
  • AND combination of the preceding conditions for leading columns in the index
  • col1 like 'ASD%' wild-card searches should not be in a leading position otherwise the condition col1 like '%ASD' does not result in a range scan.

Range scans can use unique or non-unique indexes. Range scans avoid sorting when index columns constitute theORDERBY/GROUPBY clause.

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值