暂无图片
SQL优化求助!!!
我来答
分享
smile
2023-11-22
SQL优化求助!!!

下面这个SQL有优化空间吗?

SELECT nvl(count(1), 0) TOTAL
FROM (SELECT L.*,
ROW_NUMBER() OVER(PARTITION BY L.ITEM_ID ORDER BY L.SYNC_DATE DESC) RN
FROM TABLE1 L)
WHERE 1 = 1
AND TASK_STATE = '1'
AND RN = 1
AND TASK_CODE ='1'
AND YWCODE = '2'
AND DEPT_CODE = '3'
AND SUBSTR(AREACODE, 1, 6) = '4'
AND CATALOG_CODE = '5'

我来答
添加附件
收藏
分享
问题补充
7条回答
默认
最新
广州_老虎刘

优化建议:

     更换SSD存储;  fix_control 30822446=1 ; 开并行(如果不更换存储, 意义不大, 只是用来使用更多的PGA)

暂无图片 评论
暂无图片 有用 7
暂无图片
smile
题主
2023-11-22
感谢老师指导。
和光同尘

聚合前的结果集越小越有优化空间,你光一个语句啥也看不出来

暂无图片 评论
暂无图片 有用 0
广州_老虎刘

正常来说, 这个SQL已经没有优化空间了.  但是如果有特殊情况, 比如item_id的唯一值比较少, 就可以通过一些改写操作, 再配合索引, 大幅提高执行效率.   

你的数据库版本是多少(跟sql写法是否支持, row_number分析函数是否开启了优化有关), 表有多大, 当前执行时间是多少, 希望的执行时间是多少, 表上字段的数据分布情况如何,是否有not null约束,  表上的索引情况等,  有了这些信息, 才能更好的分析和解决问题.

暂无图片 评论
暂无图片 有用 4
smile
题主
2023-11-22
相关表信息发出来了。
smile

表数量:

SQL> select count(1) from table1; COUNT(1) ---------- 967891

数据库版本:
oracle 19.17

当前执行时间:> 2分钟

希望执行时间: < 10秒
索引情况
4aacda6bdecb8b4925e1f01934586c8.png
表结构
503d4d359362137be3784085f1dd690.png
21e1f5521a5fd4b6767a0dc362d8671.png

暂无图片 评论
暂无图片 有用 0
chengang

从MySQL角度看。这个SQL可以这样优化

如果 每个ITEM_ID分组下的SYNC_DATE是唯一的

则可以建立一个索引idx(ITEM_ID,SYNC_DATE),先实现
select ITEM_ID,max(SYNC_DATE ) from L group by ITEM_ID 的松散扫描。 再用这个结果集去关联原L表。这样原L表的其它等值条件也可以使用索引了。

速度还是会比窗口函数快很多。

暂无图片 评论
暂无图片 有用 2
广州_老虎刘
2023-11-22
一般来说group by确实要比分析函数快一些, oracle也是一样. 你提到的松散扫描的前提是item_id的唯一值少, 如果没有这个前提, 虽然group by这一步比分析函数快了一点, 但是后面还要再关联原表, 大结果集之间关联走索引是不太合适的, 这样又多了一次全表扫描和hash join, 效率也差不了多少.
chengang
答主
2023-11-22
题主没有贴出 除了RN =1 其它条件的区分度,如果其它条件有较好的过滤性,也避免了两个大表相join
广州_老虎刘
2023-11-22
那你这个要求的条件有点多: 两字段唯一, 还不能有空值 , ITEM_id 的唯一值要小, where 条件过滤性要好 , 如果有这些条件, 那确实有很大优化空间.
广州_老虎刘

根据表记录数不到100万, 执行时间2分钟的事实, 可以推断出字段的平均行长应该比较长, 占的空间较多(应该占用了几个G的磁盘空间); 磁盘是普通磁盘, 不是SSD盘; PGA不够大, 因为row_number分析函数需要较多的内存, 内存放不下就要写和读临时表空间 .

你的这个版本的row_number算法是做了改进的, 但是需要在session 级别设置一个fix_control, 能减少pga的使用, 也就减少了读写临时表空间的数据量. 

另外, 使用并行能增加pga的使用, 进一步减少分析函数对临时表空间的读写. 

需要你再查查 select count(distinct ITEM_ID) from table1;   这个值如果不大, 还可以改写SQL, 这种情况提速会比较多; 否则就只能通过fix_control和并行来提速, 想达到10秒以下比较困难.

暂无图片 评论
暂无图片 有用 1
smile
题主
2023-11-22
ITEM_ID去重后是20几万,普通磁盘,已经根据addm建议将之前50G的PGA调整为60G。
董大威
SQL> select count(ITEM_ID),count(distinct ITEM_ID) from table1;
暂无图片 评论
暂无图片 有用 0
回答交流
提交
问题信息
请登录之后查看
邀请回答
暂无人订阅该标签,敬请期待~~
暂无图片墨值悬赏