[20191218]降序索引疑问4.txt

[20191218]降序索引疑问4.txt[20191218]降序索引疑问4.txt–//前几天优化一个项目,我发现许多表里面有有隐含字段,一般开发很少建立函数索引.我自己检查发现里面存在大量的降序索引.–//我感觉有点奇怪,为什么开发要

[20191218]降序索引疑问4.txt

–//前几天优化一个项目,我发现许多表里面有有隐含字段,一般开发很少建立函数索引.我自己检查发现里面存在大量的降序索引.
–//我感觉有点奇怪,为什么开发要建立大量降序索引有什么好处呢?

–//我在链接http://www.itpub.net/thread-2122088-1-1.html里面问这个问题,sqysl的解答给了我很好的提示,我通过例子说明使用降
–//序索引的一点点好处,通过例子说明:

1.环境:
SCOTT@book> @ ver1
PORT_STRING         VERSION        BANNER
——————- ————– —————————————————————————-
x86_64/Linux 2.4.xx 11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 – 64bit Production

SCOTT@book> alter system set pga_aggregate_target=4G;
System altered.

SCOTT@book> create table t (id1 number,id2 number,vc varchar2(50));
Table created.

create index i_t_id1_id2 on t (id1,id2);
create index i_t_id1desc_id2desc on t (id1 desc,id2 desc);
create index i_t_id1desc_id2 on t (id1 desc,id2 );
create index i_t_id1_id2desc on t (id1 ,id2 desc );

SCOTT@book> insert into t select rownum,rownum,lpad(“a”,50,”a”) from dual connect by level<=1e6;
1000000 rows created.

SCOTT@book> commit ;
Commit complete.

–//分析略.
SCOTT@book> select index_name,index_type,blevel,leaf_blocks,distinct_keys from dba_indexes where owner=user and table_name=”T”;
INDEX_NAME                     INDEX_TYPE                      BLEVEL LEAF_BLOCKS DISTINCT_KEYS
—————————— ————————— ———- ———– ————-
I_T_ID1_ID2                    NORMAL                               2        2623       1000000
I_T_ID1DESC_ID2DESC            FUNCTION-BASED NORMAL                2        5877       1000000
I_T_ID1DESC_ID2                FUNCTION-BASED NORMAL                2        5618       1000000
I_T_ID1_ID2DESC                FUNCTION-BASED NORMAL                2        2753       1000000
–//无论那种倒序索引,索引都比正序索引大,特别是第1个字段选择desc的情况.因为我插入的字段是自增字段.
–//倒序索引分裂都是50-50分裂.

2.测试例子:
SCOTT@book> alter session set statistics_level = all;
Session altered.

SCOTT@book> select * from (select * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=10;
       ID1        ID2 VC
———- ———- ————————————————–
   1000000    1000000 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999999     999999 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999998     999998 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999997     999997 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999996     999996 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999995     999995 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999994     999994 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999993     999993 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999992     999992 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999991     999991 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
10 rows selected.

SCOTT@book> @ dpc “” “”
PLAN_TABLE_OUTPUT
————————————-
SQL_ID  20hb1uyyqx4tf, child number 0
————————————-
select * from (select * from t where id1<=1e6 order by id1 desc,id2 )
where rownum<=10
Plan hash value: 404407004
——————————————————————————————————————————————-
| Id  | Operation                     | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
——————————————————————————————————————————————-
|   0 | SELECT STATEMENT              |                 |      1 |        |       |     4 (100)|          |     10 |00:00:00.01 |       6 |
|*  1 |  COUNT STOPKEY                |                 |      1 |        |       |            |          |     10 |00:00:00.01 |       6 |
|   2 |   VIEW                        |                 |      1 |     10 |   530 |     4   (0)| 00:00:01 |     10 |00:00:00.01 |       6 |
|   3 |    TABLE ACCESS BY INDEX ROWID| T               |      1 |   1000K|    58M|     4   (0)| 00:00:01 |     10 |00:00:00.01 |       6 |
|*  4 |     INDEX RANGE SCAN          | I_T_ID1DESC_ID2 |      1 |     10 |       |     3   (0)| 00:00:01 |     10 |00:00:00.01 |       4 |
——————————————————————————————————————————————-
Query Block Name / Object Alias (identified by operation id):
————————————————————-
   1 – SEL$1
   2 – SEL$2 / from$_subquery$_001@SEL$1
   3 – SEL$2 / T@SEL$2
   4 – SEL$2 / T@SEL$2
Predicate Information (identified by operation id):
—————————————————
   1 – filter(ROWNUM<=10)
   4 – access(“T”.”SYS_NC00004$”>=HEXTORAW(“3BFDFF”)  AND “T”.”SYS_NC00004$” IS NOT NULL)
       filter(SYS_OP_UNDESCEND(“T”.”SYS_NC00004$”)<=1000000)
32 rows selected.
–//逻辑读仅仅6个.而其它2个索引都无法达到这样的效果.

select * from (select /*+ index(t I_T_ID1DESC_ID2DESC) */ * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=10;
select * from (select /*+ index_desc(t I_T_ID1DESC_ID2DESC) */ * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=10;

select * from (select /*+ index(t I_T_ID1_ID2) */ * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=10;
select * from (select /*+ index_desc(t I_T_ID1_ID2) */ * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=10;
–//结果不在贴出.大家可以自行测试.

3.继续测试:

SCOTT@book> alter index I_T_ID1DESC_ID2 invisible;
Index altered.

SCOTT@book> select * from (select  * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=1;
       ID1        ID2 VC
———- ———- ————————————————–
   1000000    1000000 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

SCOTT@book> @ dpc “” “”
PLAN_TABLE_OUTPUT
————————————-
SQL_ID  2r7j4a5gdhpnj, child number 0
————————————-
select * from (select  * from t where id1<=1e6 order by id1 desc,id2 )
where rownum<=1

Plan hash value: 3299198703

———————————————————————————————————————————————————————-
| Id  | Operation               | Name | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
———————————————————————————————————————————————————————-
|   0 | SELECT STATEMENT        |      |      1 |        |       |       | 17500 (100)|          |      1 |00:00:00.38 |    9285 |     74 |       |       |          |
|*  1 |  COUNT STOPKEY          |      |      1 |        |       |       |            |          |      1 |00:00:00.38 |    9285 |     74 |       |       |          |
|   2 |   VIEW                  |      |      1 |   1000K|    50M|       | 17500   (1)| 00:03:30 |      1 |00:00:00.38 |    9285 |     74 |       |       |          |
|*  3 |    SORT ORDER BY STOPKEY|      |      1 |   1000K|    58M|    69M| 17500   (1)| 00:03:30 |      1 |00:00:00.38 |    9285 |     74 |    65M|  2806K|          |
|*  4 |     TABLE ACCESS FULL   | T    |      1 |   1000K|    58M|       |  2744   (1)| 00:00:33 |   1000K|00:00:00.12 |    9285 |     74 |       |       |          |
———————————————————————————————————————————————————————-

Query Block Name / Object Alias (identified by operation id):
————————————————————-

   1 – SEL$1
   2 – SEL$2 / from$_subquery$_001@SEL$1
   3 – SEL$2
   4 – SEL$2 / T@SEL$2

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

   1 – filter(ROWNUM<=1)
   3 – filter(ROWNUM<=1)
   4 – filter(“ID1″<=1000000)
32 rows selected.
–//oracle选择全表扫描.

SCOTT@book> alter index I_T_ID1DESC_ID2 visible;
Index altered.

4.再继续测试:
–//测试第1个字段正序,第2个字段倒序的情况.
SCOTT@book> select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc ) where rownum<=5;
       ID1        ID2 VC
———- ———- ————————————————–
         1          1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         2          2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         3          3 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         4          4 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         5          5 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

SCOTT@book> @ dpc “” “”
PLAN_TABLE_OUTPUT
————————————-
SQL_ID  8f5yj8c3frpnc, child number 0
————————————-
select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc )
where rownum<=5
Plan hash value: 2787951352
——————————————————————————————————————————————-
| Id  | Operation                     | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
——————————————————————————————————————————————-
|   0 | SELECT STATEMENT              |                 |      1 |        |       |     4 (100)|          |      5 |00:00:00.01 |       6 |
|*  1 |  COUNT STOPKEY                |                 |      1 |        |       |            |          |      5 |00:00:00.01 |       6 |
|   2 |   VIEW                        |                 |      1 |      5 |   265 |     4   (0)| 00:00:01 |      5 |00:00:00.01 |       6 |
|   3 |    TABLE ACCESS BY INDEX ROWID| T               |      1 |   1000K|    58M|     4   (0)| 00:00:01 |      5 |00:00:00.01 |       6 |
|*  4 |     INDEX RANGE SCAN          | I_T_ID1_ID2DESC |      1 |      5 |       |     3   (0)| 00:00:01 |      5 |00:00:00.01 |       4 |
——————————————————————————————————————————————-
Query Block Name / Object Alias (identified by operation id):
————————————————————-
   1 – SEL$1
   2 – SEL$2 / from$_subquery$_001@SEL$1
   3 – SEL$2 / T@SEL$2
   4 – SEL$2 / T@SEL$2
Predicate Information (identified by operation id):
—————————————————
   1 – filter(ROWNUM<=5)
   4 – access(“ID1″<=1000000)
31 rows selected.
–//可以发现很好第使用I_T_ID1_ID2DESC索引.逻辑读也很小,仅仅6.

SCOTT@book> alter index I_T_ID1_ID2DESC invisible;
Index altered.

select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc ) where rownum<=1;
SCOTT@book> select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc ) where rownum<=5;
       ID1        ID2 VC
———- ———- ————————————————–
         1          1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         2          2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         3          3 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         4          4 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         5          5 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

SCOTT@book> @ dpc “” “”
PLAN_TABLE_OUTPUT
————————————-
SQL_ID  8f5yj8c3frpnc, child number 0
————————————-
select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc )
where rownum<=5

Plan hash value: 2145689175

—————————————————————————————————————————————————–
| Id  | Operation                      | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |
—————————————————————————————————————————————————–
|   0 | SELECT STATEMENT               |                 |      1 |        |       |     4 (100)|          |      5 |00:00:00.01 |       6 |      1 |
|*  1 |  COUNT STOPKEY                 |                 |      1 |        |       |            |          |      5 |00:00:00.01 |       6 |      1 |
|   2 |   VIEW                         |                 |      1 |      5 |   265 |     4   (0)| 00:00:01 |      5 |00:00:00.01 |       6 |      1 |
|   3 |    TABLE ACCESS BY INDEX ROWID | T               |      1 |   1000K|    58M|     4   (0)| 00:00:01 |      5 |00:00:00.01 |       6 |      1 |
|*  4 |     INDEX RANGE SCAN DESCENDING| I_T_ID1DESC_ID2 |      1 |      5 |       |     3   (0)| 00:00:01 |      5 |00:00:00.01 |       4 |      1 |
—————————————————————————————————————————————————–
Query Block Name / Object Alias (identified by operation id):
————————————————————-
   1 – SEL$1
   2 – SEL$2 / from$_subquery$_001@SEL$1
   3 – SEL$2 / T@SEL$2
   4 – SEL$2 / T@SEL$2
Predicate Information (identified by operation id):
—————————————————
   1 – filter(ROWNUM<=5)
   4 – access(“T”.”SYS_NC00004$” IS NOT NULL AND “T”.”SYS_NC00004$”>=HEXTORAW(“3BFDFF”) )
       filter(SYS_OP_UNDESCEND(“T”.”SYS_NC00004$”)<=1000000)
32 rows selected.

–//你会发现一个奇特现象,oracle会使用”倒过来”的一个索引,也就是id1 desc,id2 asc的索引.

SCOTT@book> alter index I_T_ID1DESC_ID2 invisible;
Index altered.

SCOTT@book> select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc ) where rownum<=5;
       ID1        ID2 VC
———- ———- ————————————————–
         1          1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         2          2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         3          3 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         4          4 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         5          5 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

SCOTT@book> @ dpc “” “”
PLAN_TABLE_OUTPUT
————————————-
SQL_ID  8f5yj8c3frpnc, child number 0
————————————-
select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc )
where rownum<=5

Plan hash value: 3299198703

———————————————————————————————————————————————————————-
| Id  | Operation               | Name | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
———————————————————————————————————————————————————————-
|   0 | SELECT STATEMENT        |      |      1 |        |       |       | 17500 (100)|          |      5 |00:00:00.41 |    9279 |   9269 |       |       |          |
|*  1 |  COUNT STOPKEY          |      |      1 |        |       |       |            |          |      5 |00:00:00.41 |    9279 |   9269 |       |       |          |
|   2 |   VIEW                  |      |      1 |   1000K|    50M|       | 17500   (1)| 00:03:30 |      5 |00:00:00.41 |    9279 |   9269 |       |       |          |
|*  3 |    SORT ORDER BY STOPKEY|      |      1 |   1000K|    58M|    69M| 17500   (1)| 00:03:30 |      5 |00:00:00.41 |    9279 |   9269 |  2048 |  2048 | 2048  (0)|
|*  4 |     TABLE ACCESS FULL   | T    |      1 |   1000K|    58M|       |  2744   (1)| 00:00:33 |   1000K|00:00:00.15 |    9279 |   9269 |       |       |          |
———————————————————————————————————————————————————————-
Query Block Name / Object Alias (identified by operation id):
————————————————————-
   1 – SEL$1
   2 – SEL$2 / from$_subquery$_001@SEL$1
   3 – SEL$2
   4 – SEL$2 / T@SEL$2
Predicate Information (identified by operation id):
—————————————————
   1 – filter(ROWNUM<=5)
   3 – filter(ROWNUM<=5)
   4 – filter(“ID1″<=1000000)
32 rows selected.
–//选择的是全表扫描.

SCOTT@book> alter index i_t_id1desc_id2desc invisible;
Index altered.

SCOTT@book> select * from (select  * from t where id1<=1e6 order by id1 desc ,id2 desc ) where rownum<=1;
       ID1        ID2 VC
———- ———- ————————————————–
   1000000    1000000 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

SCOTT@book> @ dpc “” “”
PLAN_TABLE_OUTPUT
————————————-
SQL_ID  66z6w3qc77jwp, child number 0
————————————-
select * from (select  * from t where id1<=1e6 order by id1 desc ,id2
desc ) where rownum<=1
Plan hash value: 3873686303

—————————————————————————————————————————————-
| Id  | Operation                      | Name        | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
—————————————————————————————————————————————-
|   0 | SELECT STATEMENT               |             |      1 |        |       |     4 (100)|          |      1 |00:00:00.01 |       4 |
|*  1 |  COUNT STOPKEY                 |             |      1 |        |       |            |          |      1 |00:00:00.01 |       4 |
|   2 |   VIEW                         |             |      1 |      1 |    53 |     4   (0)| 00:00:01 |      1 |00:00:00.01 |       4 |
|   3 |    TABLE ACCESS BY INDEX ROWID | T           |      1 |   1000K|    58M|     4   (0)| 00:00:01 |      1 |00:00:00.01 |       4 |
|*  4 |     INDEX RANGE SCAN DESCENDING| I_T_ID1_ID2 |      1 |      1 |       |     3   (0)| 00:00:01 |      1 |00:00:00.01 |       3 |
—————————————————————————————————————————————-
–//也能很好的选择正序索引.

5.总结:
–//通过以上测试,仅仅一种特殊的情况才需要建立倒序索引.存在id1 desc,id2 asc的情况下,建议完全可反过来建立(特别对于自增序列字段),
–//就是反过来建立索引id1 ,id2 desc,这样的索引占用磁盘空间更小.
–//其它情况我看不到降序索引的优势.

[20191218]降序索引疑问4.txt

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/10424.html

(0)
上一篇 2022-12-27
下一篇 2022-12-27

相关推荐

  • mysql死锁例子_数据库死锁

    mysql死锁例子_数据库死锁最近项目中某个模块稳定复现MySQL死锁问题,本文记录死锁的发生原因以及解决办法。 1. 预备知识 1.1 表锁和行锁 表锁 表锁是MySQL中最基本的锁策略,并且是开销最小的策略。表锁会锁定整张数据

    2023-04-15
    150
  • 使用bs4.select解析网页中的标题元素

    使用bs4.select解析网页中的标题元素在网络爬取和数据分析中,常常需要使用Python对网页进行解析,获取网页中所需的数据和信息。其中,使用bs4库中的select方法来解析网页中的标题元素h1/h1,生成一个纯净、简洁的标题是一个很常见的需求。本文将从不同角度介绍使用bs4.select解析网页中的标题元素的技巧与方法。

    2024-07-19
    40
  • 关于MySQL死锁检测机制参数innodb_deadlock_detect设置的一点思考

    关于MySQL死锁检测机制参数innodb_deadlock_detect设置的一点思考微信公众号中(这里)看到一个关于MySQL的innodb_deadlock_detect与并发相关的细节,觉得比较有意思,也即innodb_deadlock_detect这个参数的设置问题 死锁检测是

    2023-02-18
    151
  • redis 基础知识点汇总

    redis 基础知识点汇总前言 本文的目的是对 redis 的基本知识点做一个简单的 梳理,不会对全部内容详解展开讲解(部分内容在之前的文章有详细讲到)。 本文涉及的内容参考下面的大纲,另外版本的问题一般都会指出来。 正文 …

    2023-02-16
    143
  • Python汉化教程

    Python汉化教程Python是一种面向对象、解释型计算机程序设计语言。其设计目的是为了让代码具有高度的可读性和简洁的语法,在各个领域都有广泛的应用。Python汉化教程旨在帮助中文用户更好地学习和使用Python语言,在此基础上,更好地完成日常开发任务。

    2024-08-04
    29
  • Python编程,无所不能

    Python编程,无所不能Python是一种面向对象、解释型的高级编程语言,由Guido van Rossum于1989年底在荷兰创造。它具有简单明了、易读易学、代码量少、可移植性强等特点,并且可以用于各种编程领域。

    2024-04-29
    69
  • sql子查询详解_把子查询作为列显示

    sql子查询详解_把子查询作为列显示本文介绍什么是 SQL 子查询,如何使用它们。子查询常用于 WHERE 子句的 IN 操作符中,以及用来填充计算列。 一、子查询 SELECT 语句是 SQL 的查询。我们迄今为止所看到的所有 SEL

    2023-05-16
    138
  • 深入理解Python中re.match对象的匹配方法

    深入理解Python中re.match对象的匹配方法re.match(pattern, string, flags=0)函数的工作原理是在给定的字符串(string)的开头(applies at the beginning of the string)匹配目标正则表达式(pattern)。如果在给定的位置未找到匹配项,则返回None。

    2024-02-28
    85

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注