DM一哥们找我优化条分页的SQL语句,结果集很小返回99行数据,废话不说安排一下。

原始SQL语句如下,保密要求,给真实的表名换了别名:

SELECT count(*)
FROM (SELECT TMP.*,
ROWNUM ROW_ID
FROM (select *
from (select pp.BIZ_PERSON_ID partyPersonOid,
pp.BIZ_PERSON_ID bizPersonId,
pp.PERSON_ID personOid,
pp.PERSON_ID personId,
pp.A01065 a01065,
jbt.task_oid taskOid,
pp.A01084 idNo,
pp.A01001 name,
jfa34.jfa34009 jfa34009,
jfa34.jfa34010 jfa34010,
jfa34.jfa34013 jfa34013,
jfa34.jfa34014 jfa34014,
bu.UNIT_ID unitOid,
bu.B01001 unitName,
bu.JFB01002 adminUnitName,
bu.PARENT_UNIT_ID parentUnitId,
(CASE
WHEN jfw01.JFW01009 = '1' THEN '是'
WHEN jfw01.JFW01009 = '0' THEN '否'
else '' end) isTfPerson,
jbt.CREATED_DATE createdDate,
jbt.UPDATED_DATE updatedDate,
jbt.PROCESS_RESULT processResult,
jbt.start_time startTime,
jbt.complete_time completeTime,
jbt.CREATED_DATE creatTaskTime,
jbt.UPDATED_DATE updateTaskTime,
jbt.item_code itemCode,
jbt.BIZ_STATUS_CODE bizStatusCode,
jbt.BIZ_STATUS_NAME bizStatusName,
jbt.PRE_BIZ_STATUS_CODE preBizStatusCode,
jbt.PRE_BIZ_STATUS_NAME preBizStatusName,
jbt.AUDIT_STATUS_CODE auditStatusCode,
jbt.AUDIT_STATUS_NAME auditStatusName,
jbt.PRE_AUDIT_STATUS_CODE preAuditStatusCode,
jbt.PRE_AUDIT_STATUS_NAME preAuditStatusName,
jbt.PROCESS_DEPT_CODE processDeptCode,
jbt.PROCESS_DEPT_NAME processDeptName,
jbti.task_item_code taskItemCode,
jbti.task_item_name taskItemName,
jbti.pre_task_item_code preTaskItemCode,
jbti.pre_task_item_name preTaskItemName,
jfa34002 dutyPost,
jfa34005 dutyPosition,
row_number() over (partition by jbt.task_oid order by jbti.UPDATED_DATE desc) as rn,
(case
when jbt.BIZ_STATUS_CODE = 'WU999' then ''
else
(SELECT bl.REMARK
FROM qqqqq bl
where bl.biz_Status_Code IN
('WU104', 'WU107', 'WM106', 'WM109', 'WM112', 'WU110', 'WM115', 'WU110',
'WM115')
AND bl.TASK_OID = jbt.TASK_OID
order by bl.CREATED_DATE DESC LIMIT 1) end) reCallOpinion,
to_char(rr.a15021, 'yyyy') as promoteYear,
rr.a15017 as reviewResultType
FROM aaaaa jbti,
bbbbb jbt
inner join ccccc pp
on
jbt.task_oid = pp.TASK_ID
left join ddddd jfw01
on
pp.biz_person_id = jfw01.biz_person_id
left join uuuuu jfa34
on
pp.biz_person_id = jfa34.biz_person_id
left join vvvvv bu
on
pp.UNIT_ID = bu.UNIT_ID
left join
(select ROW_NUMBER() OVER (PARTITION BY biz_person_id ORDER BY a15021 DESC, handle_Mark desc, id desc) AS num,
a15021,
a15017,
biz_person_id
from rrrrr) rr
on
pp.biz_person_id = rr.biz_person_id
and rr.num = '1'
WHERE jbt.task_oid = jbti.task_oid
and pp.UNIT_ID in
(select unit_oid
from sssss
where user_id = 'admin')
AND jbti.TASK_ITEM_STATUS = '1'
AND jbti.TASK_ITEM_CODE in
(select jmn.FLOW_NODE_CODE
from jjjjj jmn
where jmn.MENU_CODE = 'B742101101')
ORDER BY jbt.UPDATED_DATE DESC)
WHERE rn = 1) TMP
WHERE ROWNUM <= 100)
WHERE ROW_ID > 1;

执行时间:

DM数据库的执行计划太难看了,直接忽略,用瞪眼大法观察下SQL大致看看是哪里慢的。

这段标量子查询去掉以后,单独把SQL拿出来跑,不加外层分页代码,0.1S能出结果,137条记录,大致判断是这里导致慢的因素。

select pp.BIZ_PERSON_ID                                                                 partyPersonOid,
pp.BIZ_PERSON_ID bizPersonId,
pp.PERSON_ID personOid,
pp.PERSON_ID personId,
pp.A01065 a01065,
jbt.task_oid taskOid,
pp.A01084 idNo,
pp.A01001 name,
jfa34.jfa34009 jfa34009,
jfa34.jfa34010 jfa34010,
jfa34.jfa34013 jfa34013,
jfa34.jfa34014 jfa34014,
bu.UNIT_ID unitOid,
bu.B01001 unitName,
bu.JFB01002 adminUnitName,
bu.PARENT_UNIT_ID parentUnitId,
(CASE
WHEN jfw01.JFW01009 = '1' THEN '是'
WHEN jfw01.JFW01009 = '0' THEN '否'
else '' end) isTfPerson,
jbt.CREATED_DATE createdDate,
jbt.UPDATED_DATE updatedDate,
jbt.PROCESS_RESULT processResult,
jbt.start_time startTime,
jbt.complete_time completeTime,
jbt.CREATED_DATE creatTaskTime,
jbt.UPDATED_DATE updateTaskTime,
jbt.item_code itemCode,
jbt.BIZ_STATUS_CODE bizStatusCode,
jbt.BIZ_STATUS_NAME bizStatusName,
jbt.PRE_BIZ_STATUS_CODE preBizStatusCode,
jbt.PRE_BIZ_STATUS_NAME preBizStatusName,
jbt.AUDIT_STATUS_CODE auditStatusCode,
jbt.AUDIT_STATUS_NAME auditStatusName,
jbt.PRE_AUDIT_STATUS_CODE preAuditStatusCode,
jbt.PRE_AUDIT_STATUS_NAME preAuditStatusName,
jbt.PROCESS_DEPT_CODE processDeptCode,
jbt.PROCESS_DEPT_NAME processDeptName,
jbti.task_item_code taskItemCode,
jbti.task_item_name taskItemName,
jbti.pre_task_item_code preTaskItemCode,
jbti.pre_task_item_name preTaskItemName,
jfa34002 dutyPost,
jfa34005 dutyPosition,
row_number() over (partition by jbt.task_oid order by jbti.UPDATED_DATE desc) as rn,
to_char(rr.a15021, 'yyyy') as promoteYear,
rr.a15017 as reviewResultType
FROM aaaaa jbti,
bbbbb jbt
inner join ccccc pp
on
jbt.task_oid = pp.TASK_ID
left join ddddd jfw01
on
pp.biz_person_id = jfw01.biz_person_id
left join uuuuu jfa34
on
pp.biz_person_id = jfa34.biz_person_id
left join vvvvv bu
on
pp.UNIT_ID = bu.UNIT_ID
left join
(select ROW_NUMBER() OVER (PARTITION BY biz_person_id ORDER BY a15021 DESC, handle_Mark desc, id desc) AS num,
a15021,
a15017,
biz_person_id
from rrrrr) rr
on
pp.biz_person_id = rr.biz_person_id
and rr.num = '1'
WHERE jbt.task_oid = jbti.task_oid
and pp.UNIT_ID in
(select unit_oid
from sssss
where user_id = 'admin')
AND jbti.TASK_ITEM_STATUS = '1'
AND jbti.TASK_ITEM_CODE in
(select jmn.FLOW_NODE_CODE
from jjjjj jmn
where jmn.MENU_CODE = 'B742101101')
ORDER BY jbt.UPDATED_DATE DESC

qqqqq 表加个联合索引再跑分页语句试试。

CREATE  INDEX "IDX_TASK_BIZ" ON "qqqqq"("TASK_OID" ASC,"BIZ_STATUS_CODE" ASC) STORAGE(ON "hzgz_xcuatdb", CLUSTERBTR);

还是需要2.34S才能出结果,这个时候笔者就在想会不会是分页框架提供的分页方式不对,换个分页写法再试试。

-- 使用新的分页模板,没改语句
SELECT count(*)
FROM (SELECT *
FROM (SELECT t.*,
rownum ROW_ID
FROM (select pp.BIZ_PERSON_ID partyPersonOid,
pp.BIZ_PERSON_ID bizPersonId,
pp.PERSON_ID personOid,
pp.PERSON_ID personId,
pp.A01065 a01065,
jbt.task_oid taskOid,
pp.A01084 idNo,
pp.A01001 name,
jfa34.jfa34009 jfa34009,
jfa34.jfa34010 jfa34010,
jfa34.jfa34013 jfa34013,
jfa34.jfa34014 jfa34014,
bu.UNIT_ID unitOid,
bu.B01001 unitName,
bu.JFB01002 adminUnitName,
bu.PARENT_UNIT_ID parentUnitId,
(CASE
WHEN jfw01.JFW01009 = '1' THEN '是'
WHEN jfw01.JFW01009 = '0' THEN '否'
else '' end) isTfPerson,
jbt.CREATED_DATE createdDate,
jbt.UPDATED_DATE updatedDate,
jbt.PROCESS_RESULT processResult,
jbt.start_time startTime,
jbt.complete_time completeTime,
jbt.CREATED_DATE creatTaskTime,
jbt.UPDATED_DATE updateTaskTime,
jbt.item_code itemCode,
jbt.BIZ_STATUS_CODE bizStatusCode,
jbt.BIZ_STATUS_NAME bizStatusName,
jbt.PRE_BIZ_STATUS_CODE preBizStatusCode,
jbt.PRE_BIZ_STATUS_NAME preBizStatusName,
jbt.AUDIT_STATUS_CODE auditStatusCode,
jbt.AUDIT_STATUS_NAME auditStatusName,
jbt.PRE_AUDIT_STATUS_CODE preAuditStatusCode,
jbt.PRE_AUDIT_STATUS_NAME preAuditStatusName,
jbt.PROCESS_DEPT_CODE processDeptCode,
jbt.PROCESS_DEPT_NAME processDeptName,
jbti.task_item_code taskItemCode,
jbti.task_item_name taskItemName,
jbti.pre_task_item_code preTaskItemCode,
jbti.pre_task_item_name preTaskItemName,
jfa34002 dutyPost,
jfa34005 dutyPosition,
row_number() over (partition by jbt.task_oid order by jbti.UPDATED_DATE desc) as rn,
(case
when jbt.BIZ_STATUS_CODE = 'WU999' then ''
else
(SELECT bl.REMARK
FROM qqqqq bl
where bl.biz_Status_Code IN
('WU104', 'WU107', 'WM106', 'WM109', 'WM112', 'WU110', 'WM115', 'WU110',
'WM115')
AND bl.TASK_OID = jbt.TASK_OID
order by bl.CREATED_DATE DESC LIMIT 1) end) reCallOpinion,
to_char(rr.a15021, 'yyyy') as promoteYear,
rr.a15017 as reviewResultType
FROM aaaaa jbti,
bbbbb jbt
inner join ccccc pp
on
jbt.task_oid = pp.TASK_ID
left join ddddd jfw01
on
pp.biz_person_id = jfw01.biz_person_id
left join uuuuu jfa34
on
pp.biz_person_id = jfa34.biz_person_id
left join vvvvv bu
on
pp.UNIT_ID = bu.UNIT_ID
left join
(select ROW_NUMBER() OVER (PARTITION BY biz_person_id ORDER BY a15021 DESC, handle_Mark desc, id desc) AS num,
a15021,
a15017,
biz_person_id
from rrrrr) rr
on
pp.biz_person_id = rr.biz_person_id
and rr.num = '1'
WHERE jbt.task_oid = jbti.task_oid
and pp.UNIT_ID in
(select unit_oid
from sssss
where user_id = 'admin')
AND jbti.TASK_ITEM_STATUS = '1'
AND jbti.TASK_ITEM_CODE in
(select jmn.FLOW_NODE_CODE
from jjjjj jmn
where jmn.MENU_CODE = 'B742101101')
ORDER BY jbt.UPDATED_DATE DESC) t)
WHERE rownum <= 100)
WHERE ROW_ID >= 1;

可以看到新的分页语句0.085S就能出结果了,简直秒杀。

总结:开发框架提的分页插件有可能提供错误的分页框架,会极大影响SQL语句原有的性能,需要多测试才能知道分页语句的性能是否符合性能要求,下面笔者提供个正确的分页框架:

select *
from (select *
from (select a.*, rownum rn from (
需要分页的 SQL
     ) a)
where rownum <= 10)
where rn >= 1;

最后,提供个left join 等价改写的方式干掉上面的标量子查询,但是在本案例中等价改写方式并没有太大性能提升,仅供娱乐:

-- 改分页模板,改SQL
SELECT count(*)
FROM (SELECT *
FROM (SELECT t.*,
rownum ROW_ID
FROM (SELECT pp.BIZ_PERSON_ID partyPersonOid,
pp.BIZ_PERSON_ID bizPersonId,
pp.PERSON_ID personOid,
pp.PERSON_ID personId,
pp.A01065 a01065,
jbt.task_oid taskOid,
pp.A01084 idNo,
pp.A01001 NAME,
jfa34.jfa34009 jfa34009,
jfa34.jfa34010 jfa34010,
jfa34.jfa34013 jfa34013,
jfa34.jfa34014 jfa34014,
bu.UNIT_ID unitOid,
bu.B01001 unitName,
bu.JFB01002 adminUnitName,
bu.PARENT_UNIT_ID parentUnitId,
(CASE
WHEN jfw01.JFW01009 = '1' THEN
'是'
WHEN jfw01.JFW01009 = '0' THEN
'否'
ELSE
''
END) isTfPerson,
jbt.CREATED_DATE createdDate,
jbt.UPDATED_DATE updatedDate,
jbt.PROCESS_RESULT processResult,
jbt.start_time startTime,
jbt.complete_time completeTime,
jbt.CREATED_DATE creatTaskTime,
jbt.UPDATED_DATE updateTaskTime,
jbt.item_code itemCode,
jbt.BIZ_STATUS_CODE bizStatusCode,
jbt.BIZ_STATUS_NAME bizStatusName,
jbt.PRE_BIZ_STATUS_CODE preBizStatusCode,
jbt.PRE_BIZ_STATUS_NAME preBizStatusName,
jbt.AUDIT_STATUS_CODE auditStatusCode,
jbt.AUDIT_STATUS_NAME auditStatusName,
jbt.PRE_AUDIT_STATUS_CODE preAuditStatusCode,
jbt.PRE_AUDIT_STATUS_NAME preAuditStatusName,
jbt.PROCESS_DEPT_CODE processDeptCode,
jbt.PROCESS_DEPT_NAME processDeptName,
jbti.task_item_code taskItemCode,
jbti.task_item_name taskItemName,
jbti.pre_task_item_code preTaskItemCode,
jbti.pre_task_item_name preTaskItemName,
jfa34002 dutyPost,
jfa34005 dutyPosition,
row_number() over (PARTITION BY jbt.task_oid ORDER BY jbti.UPDATED_DATE DESC) AS rn,
(CASE WHEN jbt.BIZ_STATUS_CODE = 'WU999' THEN '' ELSE bl.REMARK END) reCallOpinion,
to_char(rr.a15021, 'yyyy') AS promoteYear,
rr.a15017 AS reviewResultType
FROM aaaaa jbti,
bbbbb jbt
left join
(select *
from (select REMARK,
TASK_OID,
row_number() over (PARTITION by TASK_OID ORDER by CREATED_DATE desc ) as rn
from qqqqq
where biz_Status_Code in ('WU104',
'WU107',
'WM106',
'WM109',
'WM112',
'WU110',
'WM115',
'WU110',
'WM115'))
where rn = 1) bl on jbt.task_oid = bl.task_oid
INNER JOIN ccccc pp
ON jbt.task_oid = pp.TASK_ID
LEFT JOIN ddddd jfw01
ON pp.biz_person_id = jfw01.biz_person_id
LEFT JOIN uuuuu jfa34
ON pp.biz_person_id = jfa34.biz_person_id
LEFT JOIN vvvvv bu
ON pp.UNIT_ID = bu.UNIT_ID
LEFT JOIN (SELECT ROW_NUMBER() OVER (PARTITION BY biz_person_id ORDER BY a15021 DESC, handle_Mark DESC, id DESC) AS num,
a15021,
a15017,
biz_person_id
FROM rrrrr) rr
ON pp.biz_person_id = rr.biz_person_id
AND rr.num = '1' WHERE jbt.task_oid = jbti.task_oid
AND pp.UNIT_ID IN
(SELECT unit_oid FROM sssss WHERE user_id = 'admin')
AND jbti.TASK_ITEM_STATUS = '1'
AND jbti.TASK_ITEM_CODE IN
(SELECT jmn.FLOW_NODE_CODE
FROM jjjjj jmn
WHERE jmn.MENU_CODE = 'B742101101')
ORDER BY jbt.UPDATED_DATE DESC) t)
WHERE rownum <= 99)
WHERE ROW_ID >= 1;

DM数据库SQL分页案例的更多相关文章

  1. 数据库SQL优化大总结之 百万级数据库优化方案(转载)

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...

  2. 关于数据库SQL优化

    1.数据库访问优化   要正确的优化SQL,我们需要快速定位能性的瓶颈点,也就是说快速找到我们SQL主要的开销在哪里?而大多数情况性能最慢的设备会是瓶颈点,如下载时网络速度可能会是瓶颈点,本地复制文件 ...

  3. 数据库sql优化总结之5--数据库SQL优化大总结

    数据库SQL优化大总结 小编最近几天一直未出新技术点,是因为小编在忙着总结整理数据库的一些优化方案,特此奉上,优化总结较多,建议分段去消化,一口吃不成pang(胖)纸 一.百万级数据库优化方案 1.对 ...

  4. 盘点几种数据库的分页SQL的写法(转)

    Data序列——盘点几种数据库的分页SQL的写法http://www.cnblogs.com/fireasy/archive/2013/04/10/3013088.html

  5. jDialects:一个从Hibernate抽取的支持70多种数据库方言的原生SQL分页工具

    jDialects(https://git.oschina.net/drinkjava2/jdialects) 是一个收集了大多数已知数据库方言的Java小项目,通常可用来创建分页SQL和建表DDL语 ...

  6. 我的sql数据库存储过程分页- -

    以前用到数据库存储过程分页的时候都是用 not in 但是最近工作的时候,随着数据库记录的不断增大,发现not in的效率 真的不行 虽然都设置了索引,但是当记录达到10w的时候就发现不行了,都是需要 ...

  7. sql分页查询(2005以后的数据库)和access分页查询

    sql分页查询: select * from ( select ROW_NUMBER() over(order by 排序条件) as rowNumber,* from [表名] where 条件 ) ...

  8. oracle,mysql,SqlServer三种数据库的分页查询的实例。

    MySql: MySQL数据库实现分页比较简单,提供了 LIMIT函数.一般只需要直接写到sql语句后面就行了.LIMIT子 句可以用来限制由SELECT语句返回过来的数据数量,它有一个或两个参数,如 ...

  9. SQL分页查询,纯Top方式和row_number()解析函数的使用及区别

    听同事分享几种数据库的分页查询,自己感觉,还是需要整理一下MS SqlSever的分页查询的. Sql Sever 2005之前版本: select top 页大小 * from 表名 where i ...

  10. MySQL 数据库增量数据恢复案例

    MySQL 数据库增量数据恢复案例 一.场景概述 MySQL数据库每日零点自动全备 某天上午10点,小明莫名其妙地drop了一个数据库 我们需要通过全备的数据文件,以及增量的binlog文件进行数据恢 ...

随机推荐

  1. 基于LLVM的海量数据排序算法研究。(二维表的排序算法)

    当待排序数据内容大于内存容量时,需将待排序内容分块,要进行排序的分块传入内存,未处于排序状态的存入外存,外存的读写时间是内存的百万倍,因此在内外存储器之间传输分块所消耗的 I/O 时间是大数据排序算法 ...

  2. shell: logging + readlog

    logging #!/bin/bash # a small tool for logging sommething # # 1. read your input # 2. save to logs f ...

  3. expect: telnet2switch

    #!/usr/bin/expect if {$argc != 1} { puts "usage: ./telnet2sswitch <r2|r3>" exit } if ...

  4. WinForm RichTextBox 加载大量文本卡死和UTF-8乱码问题

    在RichTextBox控件的使用中我们会遇到加载TXT文件的问题,通常我们会有两种处理方式. 一.加载TXT字符串,设置到RichTextBox //打开并且读取文件数据 FileStream fs ...

  5. 手动安装vur-router并引用

    安装并引用 安装 npm install vue-router 引用 步骤一:在src路径下,创建router文件夹, 其下创建index.js // router/index.js import V ...

  6. p2:认识requests库的常用方法与实战

    二.全面认识requests库的常用方法 requests是python第三方库安装命令方法如下: pip install requests python的默认的测试用来规则 1.模块名必须以test ...

  7. [PWN之路]栈溢出那些事儿

    前言 如果入门,想要学习栈溢出相关知识欢迎参考hash_hash的入门文章和我的集训wp,按照buuctf的题目一点一点做,不会的搜索到网上,并且及时在论坛发帖总结和交流.并且这里贴上一个不错的教程, ...

  8. 【技术积累】Vue.js中的CSS过渡【一】

    CSS过渡是什么 在Vue中,可以使用<transition>组件来实现CSS过渡效果.CSS过渡是指在元素的状态发生改变时,通过添加或移除CSS类来实现平滑的过渡效果. <tran ...

  9. 7、Mybatis之特殊SQL

    7.1 创建接口.映射文件和测试类 ++++++++++++++++++++++++++分割线++++++++++++++++++++++++++ 注意namespace属性值为对应接口的全限定类名 ...

  10. WPF 入门笔记 - 08 - 动画

    感谢大家对上篇博文的支持 回到正题,今天和大家分享下学习动画过程中的内容.动画对我来讲还是蛮新鲜的,大家知道在接触WPF之前我只用过Winform,而Winform中并没有动画的概念,当想要实现某些& ...