`

rownum和order by以及index的关系

阅读更多

本篇文章主要讨论rownum和排序以及索引的关系

  问题1、rownum正序是指什么?

  问题2、rownum和order by语句在一起时,执行的先后顺序是什么?order by语句如何影响rownum正序?

  问题3、rownnum与索引之间的关系?

-- Create table
  create table DAIMIN
  ( ID NUMBER not null,
  PARENTID NUMBER
  );
  alter table daimin add constraint pk_daimin primary key(id);
  SQL> select *from DAIMIN;
  ID PARENTID
  ---------- ----------
  1 6
  2 3
  5 1
  3 2


  问题1、rownum正序是指什么?

  rownum正序是指rownum的返回,是按照1,2,3依次递增,如上面的查询显示的效果

  问题2、rownum和order by语句在一起时,执行的先后顺序是什么?order by语句如何影响rownum正序?

  下面执行两个语句进行比较:

 SQL> select rownum as r, t.ID from daimin t order by t.ID;
  R ID
  ---------- ----------
  1 1
  2 2
  3 3
  4 5


  现象:是rownum是按照正序来返回的

  该语句的执行计划如下:

--------------------------------------------------------------------
  | Id | Operation | Name | Rows | Bytes | Cost |
  --------------------------------------------------------------------
  | 0 | SELECT STATEMENT | | | | |
  | 1 | COUNT | | | | |
  | 2 | INDEX FULL SCAN | PK_DAIMIN | | | |
  --------------------------------------------------------------------


  现象:使用了PK_DAIMIN这个主键索引,并且从执行计划中看出COUNT操作之后没有SORT ORDER BY操作

  (Rownum事实上在COUNT (STOPKEY)时产生)

SQL> select rownum as r, t.parentid from daimin t order by t.parentid;
  R PARENTID
  ---------- ----------
  3 1
  4 2
  2 3
  1 6


  现象:是rownum没有按照正序来返回

  该语句的执行计划如下:

--------------------------------------------------------------------
  | Id | Operation | Name | Rows | Bytes | Cost |
  --------------------------------------------------------------------
  | 0 | SELECT STATEMENT | | | | |
  | 1 | SORT ORDER BY | | | | |
  | 2 | COUNT | | | | |
  | 3 | TABLE ACCESS FULL | DAIMIN | | | |
  --------------------------------------------------------------------


  现象:没有使用索引查询 ,并且在COUNT操作之后有SORT ORDER BY操作

  分析:为什么这两句SQL语句返回的rownum不一样呢?

  主要是由于第一句使用了索引已经排好序,然后再产生Rownum,此时已经是按照parentid排好序的顺序,

  再按照parentid排序之后原来的rownum标识不会被打乱,所以返回的rownum是正序;

  而第二句则使用全表扫描,在全表扫面是查询出来的结果集是按照表中原有的记录的先后顺序来返回的,

  然后在COUNT操作时给返回的记录标记1,2,3,在标好标记之后再按照parentid字段排序,这样就将原来

  在COUNT时的顺序打乱,重新排序,所以返回的rownum不是正序。

  问题3、rownnum与索引之间的关系?是不是建了某个字段的索引都会使用索引呢(在没有改字段的where条件的情况下)?

  下面做测试试验:

  给DAIMIN表中的PARENTID字段建索引

create index DM_PARENTID on DAIMIN (PARENTID);
  select rownum as r, t.parentid from daimin t order by t.parentid;


  其执行计划:

--------------------------------------------------------------------
  | Id | Operation | Name | Rows | Bytes | Cost |
  --------------------------------------------------------------------
  | 0 | SELECT STATEMENT | | | | |
  | 1 | SORT ORDER BY | | | | |
  | 2 | COUNT | | | | |
  | 3 | TABLE ACCESS FULL | DAIMIN | | | |
  --------------------------------------------------------------------


  查询结果:

SQL> select rownum as r, t.parentid from daimin t order by t.parentid;
  R PARENTID
  ---------- ----------
  3 1
  4 2
  2 3
  1 6


  分析:给parentid字段建了索引,但是该语句并没有使用索引,仍然采用的是全表扫描,所以返回的rownum仍然不是正序。

  如果修改DAIMIN表中的PARENTID字段为not null

  alter table DAIMIN modify PARENTID not null;

  再次查询该语句的其执行计划:

---------------------------------------------------------------------
  | Id | Operation | Name | Rows | Bytes | Cost |
  ---------------------------------------------------------------------
  | 0 | SELECT STATEMENT | | | | |
  | 1 | COUNT | | | | |
  | 2 | INDEX FULL SCAN | DM_PARENTID | | | |
  ---------------------------------------------------------------------


  查询结果:

SQL> select rownum as r, t.parentid from daimin t order by t.parentid;
  R PARENTID
  ---------- ----------
  1 1
  2 2
  3 3

      4 6


  分析:将parentid字段设置为not null字段之后,由于在order by parentid时会采用parentid字段的索引DM_PARENTID,

  所以改语句查询出来的rownum的顺序是正序。

  问题:为什么给parentid字段设置为not null字段之后,此时该查询语句会使用索引呢(在没有该字段的where条件时)?

  这里主要是牵涉到order by使用索引的条件,什么情况下order by会使用索引?

  order by 使用索引是有条件的:

  1)ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序.

  2)ORDER BY中所有的列必须定义为非空.

  3)另外,如果ORDER BY中的列在where 条件中出现,也会使用索引

  上面的试验是满足了ORDER BY中列parentid为非空,所以order by parentid使用parentid字段的索引。

  对于复合索引:

  create index DM_INDEX on DAIMIN (ID, PARENTID);

  以下几句都使用了索引:

Select rownum, t.* from DAIMIN t order by ID, PARENTID; --使用复合索引DM_INDEX
  select rownum, t.* from DAIMIN t order by t.ID desc, t.PARENTID desc; --使用复合索引DM_INDEX
  Select rownum, t.* from DAIMIN t order by ID; --使用主键索引
  Select rownum, t.* from DAIMIN t order by ID desc; --使用主键索引


  以下几句不使用索引:

select rownum, t.* from DAIMIN t order by t.ID asc, t.PARENTID desc; --不使用复合索引DM_INDEX,全表扫描
  Select rownum, t.* from DAIMIN t order by PARENTID;


  (该句parentid字段还没有设置为not null时,只有复合索引DM_INDEX,此时不使用复合索引)

  总结:

  1)默认情况是按顺序先取rownum,再order by

  2)如果order by 满足使用索引的情况,则先order by,再取rownum

  order by 使用索引是有条件的:

  1)ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序.

  2)ORDER BY中所有的列必须定义为非空.

  3)另外,如果ORDER BY中的列在where 条件中出现,也会使用索引

分享到:
评论

相关推荐

    SQL ROW_NUMBER()分页比较

    select row_number() over(order by name) as rowNum,* from users ) as t where rowNum between 5000 and 5100 ``` 这种方法的缺点是需要查出所有数据,然后再进行排序和过滤,这将导致性能问题。 正确的使用...

    rowid与rownumber

    rowid 是相对不变的,除非使用 order by 语句,否则 rowid 的值将保持不变。 二、rownum 概念 rownum 是 Oracle 数据库中的另一个虚列,用于标示 SQL 语句的输出结果排序。rownum 是一个动态的值,取决于 SQL 语句...

    OracleSQL基础培训.pptx

    7. 使用ROWNUM进行分页查询,以及LEVEL、PRIOR和CONNECT BY … START WITH用于层次查询。 接下来,DDL基础涵盖了数据库结构的创建、修改和删除,例如: 1. 创建表(CREATE TABLE)、视图(CREATE VIEW)、索引...

    oracle 語法命令備忘

    ORDER BY子句用于对结果集进行排序,如`SELECT * FROM employees ORDER BY salary DESC`按薪水降序排列员工。 5. 分组(GROUP BY子句): GROUP BY用于根据一个或多个列对数据进行分组,常与聚合函数(如COUNT、...

    自动检查消除重复ID

    SELECT ID, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY (SELECT NULL)) AS RowNum FROM YourTableName GROUP BY ID HAVING COUNT(*) > 1 ) SELECT * FROM Dupes WHERE RowNum > 1 ``` 这将展示每个重复...

    MSSQL 分页

    配合`PARTITION BY`和`ORDER BY`,可以创建分组内的行号或全局行号。例如,获取第11到20行的数据: ```sql WITH CTE AS ( SELECT *, ROW_NUMBER() OVER (ORDER BY SomeColumn) AS RowNum FROM YourTable ) ...

    持续更新, 整理mysql、oracle数据库相关 笔试面试题,主要为了应对面试过程中遇到的sql题目

    1. **选择查询(SELECT)**:理解如何从一个或多个表中选择数据,包括使用WHERE子句进行条件过滤,使用GROUP BY和HAVING对数据进行分组和过滤,以及使用ORDER BY进行排序。 2. **联接查询(JOIN)**:包括内连接...

    Oracle的SQL分页实践

    使用JDBC时,可以结合LIMIT和OFFSET子句(Oracle不支持LIMIT,但可以通过ROWNUM模拟)来实现分页,而在Hibernate中,可以使用Criteria API或HQL的`setFirstResult`和`setMaxResults`方法来实现相同的功能。...

    Oracle常用SQL语句复习

    Oracle数据库是全球广泛使用的大型关系型数据库管理系统,其SQL(结构化查询语言)在数据管理、分析和应用开发中扮演着核心角色。本篇将基于"Oracle常用SQL语句复习"这一主题,深入探讨Oracle SQL的基本语法和常用...

    oracle常用经典sql查询

    在Oracle中,SQL不仅可以用于查询数据,还可以用于插入、更新、删除数据,以及创建和管理数据库对象。以下是一些Oracle SQL查询的经典用法,这些技巧对于数据库管理员和开发人员来说都是十分实用的。 1. **基本查询...

    Oracle学习笔记.doc

    - 采用ROWNUM分页查询: `SELECT * FROM (SELECT ROWNUM AS rownum, * FROM (SELECT * FROM employees ORDER BY salary DESC) WHERE ROWNUM ) WHERE rownum > 5;`. #### 十四、添加、修改和删除 - **数据操作**包括...

    sql编写中文手册-详细教程

    在IT行业中,SQL(Structured Query Language)是一种用于管理和处理关系数据库的强大语言,广泛应用于数据查询、更新、插入和删除等操作。本教程“SQL编写中文手册-详细教程”专为Oracle数据库系统设计,旨在帮助...

    oracle-sql.rar_oracle

    下面,我们将深入探讨Oracle SQL的一些经典查询语句,以及它们的基础和扩展应用。 一、基础SQL查询语句 1. SELECT语句:这是SQL中最基本的查询语句,用于从数据库表中获取数据。例如,`SELECT * FROM table_name;`...

    数据库管理员日常工作中必备的sql列表.pdf

    1. 监控索引使用:`ALTER INDEX &index_name MONITORING USAGE` 和 `ALTER INDEX &index_name NOMONITORING USAGE` 用于开启或关闭对特定索引使用情况的监控。`SELECT * FROM v$object_usage WHERE index_name = &...

    Oracle 9i SQL

    SQL(Structured Query Language)是用于管理和处理关系数据库的标准编程语言,而Oracle 9i SQL则在此基础上进行了扩展和优化,以适应更复杂的数据库应用场景。 1. SQL基础应用: - 数据查询:SQL的基础在于SELECT...

    数据库问题

    SELECT n.*, ROW_NUMBER() OVER (ORDER BY column_name) as row_num FROM table_name n ) WHERE row_num BETWEEN 10 AND 20; ``` ### 6. Oracle中的左连接与右连接 - **左连接**(LEFT JOIN)返回左表的所有行...

    批量过程SQL 相同部门中年龄最大 廷时 分页

    ORDER BY time_id DESC SET @MyCounter = @MyCounter + 1 END select userid insert into select * from person; select * insert into person values('a','b',20,'110') select * from emp where hiredate ...

    Oracle数据库日常管理方案精.docx

    - **数据库备份情况与可恢复性检查**:确保备份的有效性和完整性,以及在紧急情况下能够快速恢复数据。 #### 三、数据库性能监控管理 数据库性能监控管理是数据库管理的重要组成部分,其目的是为了预防风险事件的...

Global site tag (gtag.js) - Google Analytics