Oracle ——数据库 SQL 分页性能分析
本文内容
- 创建测试表 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 选择,从而得到 beginrno 和 endrno 之间的行。
在执行计划中,从 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 |
参考资料
- Using EXPLAIN PLAN http://docs.oracle.com/cd/B28359_01/server.111/b28274/ex_plan.htm#PFGRF009
- Statistics Descriptions http://docs.oracle.com/cd/B28359_01/server.111/b28320/stats002.htm#i375475
Oracle ——数据库 SQL 分页性能分析相关推荐
- oracle数据库优化-IO性能分析优化
在部署了ORACLE数据库的服务器上,我们大家或多或少的遇到过下列情况: 1. 业务系统运行缓慢,作为系统管理员需要检查包括IO在内的系统资源,这时系统管理员.存储管理员可能得到DBA(数据库管理员) ...
- 崔华 oracle简历,2013数据库大会:崔华-基于Oracle的SQL优化案例分析
2013数据库大会:崔华-基于Oracle的SQL优化案例分析 崔华的新书即将出版,其数据库大会上的演讲也非常精彩,他的新书十分值得期待. 2013年中国数据库技术大会第二天的"Oracle ...
- Sql Server 性能分析4 –数据库大小,数据库表大小综合性分析报表输出
Sql Server 性能分析4 –数据库大小,数据库表大小综合性分析报表输出 一:MS SQL Report Server 报表的制作. 1.打开Microsoft Visual Studio 20 ...
- 2场直播丨Oracle数据库SQL执行计划的取得和解析、一次特殊的 Oralce 硬解析性能问题的技术分享...
1. Oracle数据库SQL执行计划的取得和解析- 2021.02.23 2月23日(周二)晚八点直播课,Oracle优化资深专家陈晓辉,以专业ORACLE数据库技术支持工程师的角度讲解SQL文的执 ...
- 163.Oracle数据库SQL开发之 SQL优化——优化工具
163.Oracle数据库SQL开发之 SQL优化--优化工具 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/50186075 ...
- MYSQL批量插入数据库实现语句性能分析
MYSQL批量插入数据库实现语句性能分析 假定我们的表结构如下 代码如下 CREATE TABLE example ( example_id INT NOT NULL, name VARCHAR( ...
- oracle数据库----SQL语句的实践(应用实例)
oracle数据库----SQL语句的实践(应用实例) 创建表工资表salary,包括员工号emp_id,员工名emp_name,员工月基本工资monthsal,员工月总发工资totalsal. cr ...
- oracle表结构修改回滚,87.Oracle数据库SQL开发之 修改表内存——数据库事务的提交和回滚...
87.Oracle数据库SQL开发之 修改表内存--数据库事务的提交和回滚 数据库事务(transaction)就是一组SQL语句,这组SQL语句时一个逻辑工作单元. 要永久性的记录事务中SQL语句的 ...
- oracle数据库sql培训,Oracle数据库SQL语言实战培训教程(全面、详细、案例、精讲)套餐...
风哥oracle数据库SQL语言实战培训教程(案例.精讲)套餐,DBA必备技能. 套餐介绍: 风哥Oracle数据库SQL语言实战培训教程(案例.精讲)套餐,DBA必备技能. 内容: SQL语言基础入 ...
最新文章
- java好还是python好-学Python 好还是java 好?
- python怎么画条形图-如何在Bokeh(Python)中绘制水平条形图
- c语言程序存为bin程序,对文件进行加密与解密(c语言)-bin文件打开
- Cognos CFG-ERR-0103 无法启动 IBM Cognos 服务
- JAVA中char和string的区别
- 设置QtreeWidget水平滚动条
- 线程通信的经典问题:生产者消费者问题
- 计算机数学基础符号,《计算机数学基础(2)—离散数学》+谓词逻辑.doc
- vs2013 提交 github
- 开发 系统键盘发送按钮不可点击_HoloLens开发指南(2)---HoloLens模拟器介绍
- Mac OS端如何使用fastboot工具
- 使用arcgis修改行政区划图边界
- 我的计算机 不显示桌面存储路劲,win10系统保存文件路径在桌面无法显示的操作步骤...
- Unity HDRP室外场景打光流程分享(上篇)-UE4场景转Unity HDRP
- Nginx 基础配置
- 软件测试外包干了4年,感觉废了..
- 关于路由器的配置参数
- SHT30 温湿度传感器,检验不通过,通讯不稳定(经常读到FF)问题处理
- idea 离线安装translation 谷歌翻译
- github上如何删除一个项目(仓库)
热门文章
- 活动报名 | DEF CON之后,最令人期待的网络安全盛会(内附赠票)
- 百度悄然发布Deep Vioce 3
- 亚马逊在德国新设AI研发中心,与马克思普朗克系统研究所亲密合作
- Python之旅.第八章.网络编程
- BFS - 求最短路径
- 分布式 和 集群的区别
- Linux下限制用户通过SFTP访问指定目录
- 为学校食堂提供“自提柜”,爽提获650万元Pre-A轮融资
- oracle 的“+”和“,”连接表的方式
- 诡异奇怪的“虚拟硬盘可用空间不足”告警