【问题标题】:How to optimize this query in Oracle 12.1.0.2?如何在 Oracle 12.1.0.2 中优化此查询?
【发布时间】:2019-07-04 15:47:15
【问题描述】:

考虑这个 SQL 语句:

select *
  from chamado.servico se
  join chamado.chamado ch on ch.id_servico=se.id_servico
  join chamado.statuschamado sc on sc.id_statuschamado=ch.id_statuschamado
 where sc.id_statuschamado=1
;

现在考虑相应的执行计划:

现在请密切注意红框!过滤谓词 (CH.ID_STATUSCHAMADO=1)。它不在查询中,而且是最昂贵的操作。

SERVICO 表少于 200 行,STATUSCHAMADO 表少于 10 行,但CHAMADO 表多于 70000 行。

我打算只在 STATUSCHAMADO 和 SERVICO 上进行全表扫描的连接,这应该对 Oracle 施加少量开销。

我的陈述有什么问题?

更新 1

我有以下指标:

  1. CHAMADO.ID_CHAMADO (PK)
  2. CHAMADO.ID_SERVICO
  3. CHAMADO.ID_AREAATENDIMENTO
  4. SERVICO.ID_SERVICO (PK)
  5. AREAATENDIMENTO.ID_AREAATENDIMENTO (PK)

【问题讨论】:

  • 请告诉我们您已经在这些表上创建了哪些索引。请注意,SELECT * 通常不是索引友好的东西。如果您真的不需要所有列,那么只需列出您真正需要的列。
  • 此查询需要至少使用chamado.servico(id_servico) chamado.chamado(id_servico, id_statuschamado)chamado.statuschamado(id_statuschamado) 上的索引来消除嵌套循环需要,除非 Oracle 优化器选择将嵌套循环作为(部分关闭)访问计划一个原因..
  • “过滤谓词 (CH.ID_STATUSCHAMADO=1)。它不在查询中,它是最昂贵的操作。” 很可能是一个低可能的唯一值的数量对吗?如果是这种情况,使用每个值分区可能是一个更好的选择。
  • @RaymondNijland:我按照您的建议创建了索引,总体成本确实下降到了 50%,所以这是一个改进!关于CH.ID_STATUSCHAMADO=1,是的,该列在CHAMADO 中提供了低选择性,这就是为什么我在STATUSCHAMADO 中添加了一个连接,期望在那里进行全表扫描。
  • "是的,该列在 CHAMADO 中提供了低选择性,这就是为什么我向 STATUSCHAMADO 添加了一个连接,期望在那里进行全表扫描。" 也许你可以强制优化器用交付的桌子来做到这一点......INNER JOIN (SELECT ... ) alias 方法如果你在这里抓住我的观点......

标签: oracle oracle12c


【解决方案1】:

“过滤谓词 (CH.ID_STATUSCHAMADO=1)...不在查询中” - 可能不是直接的,但这就是实际发生的情况。你在sc.ID_STATUSCHAMADO = ch.ID_STATUSCHAMADO 上加入STATUSCHAMADO scCHAMADO ch,然后在你的WHERE 子句中你有sc.ID_STATUSCHAMADO = 1

数据库足够聪明,可以确定sc.ID_STATUSCHAMADO 将始终为1,因此可以替换CHAMADO.ID_STATUSCHAMADO = 1。您也可以尝试反转 STATUSCHAMADO 上新索引上的字段 - 尝试使用 (ID_STATUSCHAMADO, ID_SERVICO)(ID_SERVICO, ID_STATUSCHAMADO)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-15
    • 1970-01-01
    • 2017-03-01
    • 2023-04-02
    • 1970-01-01
    相关资源
    最近更新 更多