暂无图片
oracle执行计划问题
我来答
分享
ora_221
2024-08-08
oracle执行计划问题

问题:sql执行时正常应该走索引扫描T_BUSI_RUN表根据时间筛选少量数据,从执行计划来看时间筛选条件未生效,走的全表扫描,改写sql后执行计划正常

除了改写sql,是否可以从数据库层面解决

sql及执行计划见附件

我来答
添加附件
收藏
分享
问题补充
5条回答
默认
最新
ora_221
上传附件:sql及执行计划.txt
暂无图片 评论
暂无图片 有用 0
打赏 0
ora_221
题主
2024-08-08
sql改写,将where改为and where SCSJ >= to_date('2024-08-01 00:00:00','YYYY-MM-DD HH24:MI:SS') AND SCSJ <= to_date('2024-08-01 22:02:21','YYYY-MM-DD HH24:MI:SS') ----->> and SCSJ >= to_date('2024-08-01 00:00:00','YYYY-MM-DD HH24:MI:SS') AND SCSJ <= to_date('2024-08-01 22:02:21','YYYY-MM-DD HH24:MI:SS')
ora_221
上传附件:sql改写后.txt
暂无图片 评论
暂无图片 有用 0
打赏 0
手机用户7421

可以从数据库层面尝试以下方法来解决此问题:


一、收集统计信息


  1. 原因:

    • 数据库的统计信息对于优化器选择合适的执行计划至关重要。如果统计信息不准确或过时,优化器可能会做出错误的决策,例如选择全表扫描而不是索引扫描。
  2. 操作步骤:

    • 使用 DBMS_STATS 包来收集相关表和索引的统计信息。
    • 例如,对于 T_BUSI_RUN 表:



     BEGIN
       DBMS_STATS.GATHER_TABLE_STATS(ownname => 'schema_name', tabname => 'T_BUSI_RUN');
     END;
     /
复制


  • 同时也可以收集索引的统计信息:



     BEGIN
       DBMS_STATS.GATHER_INDEX_STATS(ownname => 'schema_name', indname => 'index_name_on_T_BUSI_RUN');
     END;
     /
复制


  1. 注意事项:
    • 收集统计信息可能会消耗一定的系统资源和时间,因此最好在系统负载较低的时候进行操作。


二、检查索引是否可用和有效


  1. 原因:

    • 索引可能因为各种原因变得不可用或无效,例如索引损坏、数据分布变化导致索引不再高效等。
  2. 操作步骤:

    • 检查索引是否存在:



     SELECT index_name FROM all_indexes WHERE table_name = 'T_BUSI_RUN';
复制


  • 确认索引是否有效:



     SELECT status FROM user_indexes WHERE index_name = 'index_name_on_T_BUSI_RUN';
复制


  • 如果索引无效,可以尝试重建索引:



     ALTER INDEX index_name_on_T_BUSI_RUN REBUILD;
复制


  1. 注意事项:
    • 重建索引会占用一定的时间和资源,并且在重建期间会锁定表,可能会影响其他正在进行的操作。


三、调整优化器参数


  1. 原因:

    • 优化器参数可以影响优化器的决策行为。通过调整这些参数,可以引导优化器更倾向于选择索引扫描。
  2. 操作步骤:

    • 例如,可以调整 OPTIMIZER_INDEX_COST_ADJ 参数,该参数用于调整索引访问成本的估算。较小的值会使优化器更倾向于选择索引扫描。


收起


sql

复制

     ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ = n; -- n 是一个合适的数值,通常在 1 到 100 之间
复制


  • 还可以调整其他相关的优化器参数,如 OPTIMIZER_MODE(选择优化器的模式,如 ALL_ROWS、FIRST_ROWS 等)。


  1. 注意事项:
    • 调整优化器参数需要谨慎,因为不正确的参数设置可能会导致其他性能问题或错误的执行计划。在调整参数之前,最好了解每个参数的含义和影响,并在测试环境中进行充分的测试。
暂无图片 评论
暂无图片 有用 0
打赏 0
ora_221
题主
2024-08-12
首先感谢答复! 这个问题是在数据库迁移之后在目标库出现的(逻辑导出导入),源库的执行计划没有问题 目标库: 1.索引及状态正常(sql中关联的几个表),之前查过,原sql执行计划来看时间筛选条件未生效所以没有走索引,sql改写后时间筛选条件才生效且执行计划是走索引 2.表的统计信息之前收集过(sql中关联的几个表),索引的统计信息确实还没有收集,我试一下看
ora_221
题主
2024-08-12
我还补充一下hint强制走索引执行计划显示是可以走索引,但是rows列还是61M,最后where用别的条件即使筛选一行数据rows列还是61M,说明最后where的条件没有生效,在源库没有问题
ora_221
题主
2024-08-12
索引没有问题,去掉右连接部分就是正常的,或者右连接改左连接或者改成join都没问题,都可以走索引且按照where条件筛选出部分数据
广州_老虎刘

把where改成and的这个改写是不等价的;

原SQL的right join实际上是inner join, 而将where改写成and后, right join仍然是outer join.   后者的结果集理论上要>=前者的结果集;

有可能迁移前后两库的参数配置不一样. 建议对该SQL迁移前后的库各采集sqlhc信息进行分析.

暂无图片 评论
暂无图片 有用 0
打赏 0
ora_221
题主
2024-08-13
感谢大佬的解答! 根据您说的:原SQL的right join实际上是inner join。 那是否将right join改为join就是等价的了(这个改写我也测试过,在目标库改写后执行计划是正常的)
广州_老虎刘

原SQL将righ join改成inner join是没问题的, 因为这个right join本身就是一个inner join的逻辑,  但是为什么优化器没有使用正确的执行计划, 根据现有的信息, 还是看不出来.  

暂无图片 评论
暂无图片 有用 0
打赏 0
回答交流
Markdown


请输入正文
提交
相关推荐
请教各位,oracle的表我有个字段已经删除了,但是数据字典里出来一个这字段,该如何去掉?
回答 3
应该是一个varchar列被设置了unused
列级(敏感字段)访问控制
回答 3
如果是应用那写一个不带那个字段的SQL就可以了。另外如果觉得创建视图的改动大,那DATAMASK和VPD恐怕更不能接受了,你可以查下相关资料。
oracle EMCC13 怎么在windows上安装代理?
回答 1
https://www.onitroad.com/jc/sol/installoraclemanagementagentomaonwindows.html
Oracle19c linux centos7.6如何配置oracle 的ACL
回答 1
官方文档参考:https://docs.oracle.com/database/121/ARPLS/dnetworkacladm.htmARPLS148首先要创建一个ACL。BEGINDBMSNETW
expdp可以只导出图片格式的那个字段吗?
回答 1
建议参考下杨长老以前发的文章http://blog.itpub.net/31556440/viewspace2639782/
请问oracle10g集群怎么启动监听?
回答 1
srvctlstartlistenern&lt;节点名&gt;lLISTENER
Oracle 查表结构:desc tablename 这个语句没用吗?
回答 1
已采纳
DESCtablenameSELECTDBMSMETADATA.GETDDL(‘TABLE’,‘数据表名’)FROMDUAL;怀疑你是user没找对
Oracle OGG:如果做数据的初始化同步,将 A 服务器上的 USER1的T1 表迁到服务器B, 还能继续数据同步?
回答 1
已采纳
先把两边的OGG进程配置好,应该是单向的A到B吧。那么A端有EXTRACT,DATAPUMP,B端有REPLICAT。应该有个INITIALLOAD的作法。可以将A上的表EXPDP出来,并记录当时的S
ORA-1466
回答 10
看下数据库种有没有TIMESTAMPWITHLOCALTIMEZONE类型的字段,如果有需要删除。然后停应用和job,修改dbtimezone后重启。对数据和系统没什么影响,可以在测试环境测试下。
Oracle 客户端时间一定取的是库的时间?
回答 2
的确sysdate是库的时间,但是注意时区,客户端会话是可以定义时区的,因此会出现不同客户端同时查同一个库的sysdate不一样,但它只是由于时区不一致而显示得不一样,实际上是一样的