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

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

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

sql及执行计划见附件

我来答
添加附件
收藏
分享
问题补充
5条回答
默认
最新
ora_221
上传附件:sql及执行计划.txt
暂无图片 评论
暂无图片 有用 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
手机用户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
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
ora_221
题主
2024-08-13
感谢大佬的解答! 根据您说的:原SQL的right join实际上是inner join。 那是否将right join改为join就是等价的了(这个改写我也测试过,在目标库改写后执行计划是正常的)
广州_老虎刘

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

暂无图片 评论
暂无图片 有用 0
回答交流
提交
问题信息
请登录之后查看
附件列表
请登录之后查看
邀请回答
暂无人订阅该标签,敬请期待~~
暂无图片墨值悬赏