本文内容

  • 创建测试表 test 及其数据
  • 创建 test 表索引
  • 创建 test 表的统计数据
  • 测试数据分布情况
  • 演示三种数据库分页的性能
  • 总结
  • 参考资料

本文内容并不新鲜,很早就有人写过,但那毕竟是别人的。还是自己动手看看较好。本文使用 Oracle 11g Release 1 (11.1)。

另外,执行计划和统计信息的具体含义,参看本文最后的参考资料链接。

创建测试表 test 及其数据


利用 Oracle 自己的视图,伪造一个测试表,并插入测试数据。即便是新装的 Oracle,也会有将近 56000 行数据。测试表有四个字段,分别表示类别 ID,产品名称,价格和供应商。

SQL> drop table test
2 /
 
Table dropped
 
SQL> create table test
2 as select mod(object_id,4)*10 category_id,
3 object_name product_name,
4 object_id price,
5 rpad('a',5,'b') supplier
6 from all_objects order by 2,1
7 /
 
Table created
 
SQL>

创建 test 表索引


演示数据库分页时,我们使用了 category_id 为过滤条件,并用 product_name 字段排序,所以为它们建立组合索引。

SQL> create index test_cid_pname on test(category_id,product_name)
2 /
 
Index created
 
SQL>

创建 test 表的统计数据


利用 ANALYZE 语句统计 test 表,和其所有索引以及索引列。

SQL> analyze table test compute statistics
  2  for table
  3  for all indexes
  4  for all indexed columns
  5  /
 
Table analyzed
 
SQL> select t.table_name,
  2         t.num_rows,
  3         t.blocks,
  4         t.empty_blocks,
  5         t.avg_space,
  6         t.avg_row_len,
  7         t.sample_size,
  8         t.last_analyzed
  9    from user_tables t
 10   where T.table_name = 'TEST'
 11  /
 
TABLE_NAME    NUM_ROWS       BLOCKS EMPTY_BLOCKS  AVG_SPACE AVG_ROW_LEN SAMPLE_SIZE LAST_ANALYZED
---------- ---------- ---------- ------------ ---------- ----------- ----------- --------------------
TEST                65058           821              75           863             86         65058     2012-9-10 11:02:45
 
SQL>

测试数据分布情况


在演示数据库分页前,先大概了解数据情况。已上面方式创建的测试表和其数据,即便是新安装的 Oracle 数据库,也又差不多 6 万条数据。

分析后,可以看出 test 表,有 65058 行,使用了 821 个数据块,平均行长度为 86。

执行下面 SQL 语句,查看一下各个类别的数据都有多少条。类别是之后分页的其中一个条件。

SQL> select t.category_id, count(t.category_id) as categorycount
  2    from test t
  3   group by t.category_id
  4   order by t.category_id asc
  5  /
 
CATEGORY_ID CATEGORYCOUNT
----------- -------------
          0         16266
         10         16290
         20         16283
         30         16219
 
SQL>

测试表的数据,有四个类别,每个类别都有 1.6 万条数据。

演示三种数据库分页的性能


下面所有 SQL 语句中的 category_id 为类别 ID;beginrno 为开始行号;endrno 为结束行号。它们都是需要输入的回话变量。

作法 1

1, 先选择指定类别的所有行,并排序。

2, 再在此内部视图选择开始行号 beginrno 和结束行号 endrno 之间的所有数据。

执行计划是“倒”着看的。

从执行计划上看,从始至终数据库都处理类别为 0 所有的数据行(16266 行)。在过滤类别时,进行了全表扫描,文中开始创建索引没有使用。最后为了获得指定开始和结束行号的数据。

这显然很多余。因为,既然是分页,我们只关心开始行号和结束行号之间的数据,至少,刚开始,只关心结束行号之前的数据。另外,cost 列值也不小,为了排序还使用了 1608K 的临时表空间。这要是在互联网上还了得。

统计信息也反映出,consistent gets 值很大,接下来的 sorts(memory) 值还为 1。该 SQL 语句造成 Oracle 在内存中排序 16266 行数据。

其中,category_id 为 类别ID;beginrno 为开始行号;endrno 为结束行号。

作法 2

既然没必要全部获,就可以先获得 endrno 之前的数据,再利用 beginrno 截取。

1, 先选择指定类别的行,并排序。

2, 再次内部视图选择 endrno 之前的所有行。

3, 最后利用 beginrno 选择,从而得到 beginrnoendrno 之间的行。

在执行计划中,从 ROWS、COST、TIME 看上去比作法 1 好多了,数值明显减少。其中,STOPKEY 起了重要作用。它为了 TOP n 操作做了优化,即本例 SQL 的内部语句:

select rownum rno, a.*
  from (select *
          from test
         where category_id = &category_id
         order by product_name) a
 where rownum <= &endrno

从统计信息看,consistent gets 值也减少了。sorts(memory) 值是 0。

作法 3

根据作法 2,选择过滤条件以及开始行号和结束行号,获得行 ROWID,再根据获得制定行 ROWID 的记录。这种看起来有点多余,但的确有效。

总结


如下表所示,是本文使用数据库分页的三种形式。

表 1 三种数据库分页

作法

SQL 语句

描述

作法 1

select *
   from (select rownum rno, a.*
           from (select *
                   from test
                  where category_id = &category_id
                  order by product_name) a)
  where rno between &beginrno and &endrno

 

作法 2

select *
  from (select rownum rno, a.*
          from (select *
                  from test
                 where category_id = &category_id
                 order by product_name) a
         where rownum <= &endrno)
 where rno >= &beginrno

 

作法 3

select *
  from test
 where rowid in (select rid
                   from (select rownum rno, rowid rid
                           from (select rowid
                                   from test
                                  where category_id = &category_id
                                  order by product_name)
                          where rownum <= &endrno)
                  where rno >= &beginrno)

 

如下表所示,是本文三种数据库分页方式的统计信息。

表 2 三种数据库分页的统计信息

统计信息

作法1

作法2

作法3

recursive calls

0

1

1

db block gets

0

0

0

consistent gets

804

234

28

physical gets

0

0

0

redo size

0

0

0

bytes sent via SQL*Net to client

1154

1154

1058

bytes received via SQL*Net from client

416

416

416

SQL*Net roundtrips to/from client

3

4

3

sorts(memory)

1

0

0

sorts(disk)

0

0

0

rows processed

11

11

11

参考资料


Oracle ——数据库 SQL 分页性能分析相关推荐

  1. oracle数据库优化-IO性能分析优化

    在部署了ORACLE数据库的服务器上,我们大家或多或少的遇到过下列情况: 1. 业务系统运行缓慢,作为系统管理员需要检查包括IO在内的系统资源,这时系统管理员.存储管理员可能得到DBA(数据库管理员) ...

  2. 崔华 oracle简历,2013数据库大会:崔华-基于Oracle的SQL优化案例分析

    2013数据库大会:崔华-基于Oracle的SQL优化案例分析 崔华的新书即将出版,其数据库大会上的演讲也非常精彩,他的新书十分值得期待. 2013年中国数据库技术大会第二天的"Oracle ...

  3. Sql Server 性能分析4 –数据库大小,数据库表大小综合性分析报表输出

    Sql Server 性能分析4 –数据库大小,数据库表大小综合性分析报表输出 一:MS SQL Report Server 报表的制作. 1.打开Microsoft Visual Studio 20 ...

  4. 2场直播丨Oracle数据库SQL执行计划的取得和解析、一次特殊的 Oralce 硬解析性能问题的技术分享...

    1. Oracle数据库SQL执行计划的取得和解析- 2021.02.23 2月23日(周二)晚八点直播课,Oracle优化资深专家陈晓辉,以专业ORACLE数据库技术支持工程师的角度讲解SQL文的执 ...

  5. 163.Oracle数据库SQL开发之 SQL优化——优化工具

    163.Oracle数据库SQL开发之 SQL优化--优化工具 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/50186075 ...

  6. MYSQL批量插入数据库实现语句性能分析

    MYSQL批量插入数据库实现语句性能分析 假定我们的表结构如下 代码如下   CREATE TABLE example ( example_id INT NOT NULL, name VARCHAR( ...

  7. oracle数据库----SQL语句的实践(应用实例)

    oracle数据库----SQL语句的实践(应用实例) 创建表工资表salary,包括员工号emp_id,员工名emp_name,员工月基本工资monthsal,员工月总发工资totalsal. cr ...

  8. oracle表结构修改回滚,87.Oracle数据库SQL开发之 修改表内存——数据库事务的提交和回滚...

    87.Oracle数据库SQL开发之 修改表内存--数据库事务的提交和回滚 数据库事务(transaction)就是一组SQL语句,这组SQL语句时一个逻辑工作单元. 要永久性的记录事务中SQL语句的 ...

  9. oracle数据库sql培训,Oracle数据库SQL语言实战培训教程(全面、详细、案例、精讲)套餐...

    风哥oracle数据库SQL语言实战培训教程(案例.精讲)套餐,DBA必备技能. 套餐介绍: 风哥Oracle数据库SQL语言实战培训教程(案例.精讲)套餐,DBA必备技能. 内容: SQL语言基础入 ...

最新文章

  1. java好还是python好-学Python 好还是java 好?
  2. python怎么画条形图-如何在Bokeh(Python)中绘制水平条形图
  3. c语言程序存为bin程序,对文件进行加密与解密(c语言)-bin文件打开
  4. Cognos CFG-ERR-0103 无法启动 IBM Cognos 服务
  5. JAVA中char和string的区别
  6. 设置QtreeWidget水平滚动条
  7. 线程通信的经典问题:生产者消费者问题
  8. 计算机数学基础符号,《计算机数学基础(2)—离散数学》+谓词逻辑.doc
  9. vs2013 提交 github
  10. 开发 系统键盘发送按钮不可点击_HoloLens开发指南(2)---HoloLens模拟器介绍
  11. Mac OS端如何使用fastboot工具
  12. 使用arcgis修改行政区划图边界
  13. 我的计算机 不显示桌面存储路劲,win10系统保存文件路径在桌面无法显示的操作步骤...
  14. Unity HDRP室外场景打光流程分享(上篇)-UE4场景转Unity HDRP
  15. Nginx 基础配置
  16. 软件测试外包干了4年,感觉废了..
  17. 关于路由器的配置参数
  18. SHT30 温湿度传感器,检验不通过,通讯不稳定(经常读到FF)问题处理
  19. idea 离线安装translation 谷歌翻译
  20. github上如何删除一个项目(仓库)

热门文章

  1. 活动报名 | DEF CON之后,最令人期待的网络安全盛会(内附赠票)
  2. 百度悄然发布Deep Vioce 3
  3. 亚马逊在德国新设AI研发中心,与马克思普朗克系统研究所亲密合作
  4. Python之旅.第八章.网络编程
  5. BFS - 求最短路径
  6. 分布式 和 集群的区别
  7. Linux下限制用户通过SFTP访问指定目录
  8. 为学校食堂提供“自提柜”,爽提获650万元Pre-A轮融资
  9. oracle 的“+”和“,”连接表的方式
  10. 诡异奇怪的“虚拟硬盘可用空间不足”告警