Oracle DB:为什么重写此查询会使它快很多倍?

时间:2018-08-31 11:14:23

标签: sql oracle relational-database sqlperformance

我有一个查询需要大约90秒才能执行。用不同的方式稍微重新编写查询后,查询将在1.5秒内运行。您能解释一下为什么运行速度更快吗?

上下文

我有一个查询,它获取记录列表-将这些记录添加到资产列表,然后将这些资产添加到人员列表,再将这些人员添加到另一个人员列表(他们的经理)。

为便于说明,可以说我们正在谈论新的销售线索列表,并且我们希望将这些线索与我们正在销售的服务,这些服务的所有者及其经理一起加入。 。

表格

我们要从中提取3个对象:

1)'sales_leads'表-具有一个索引的简单本地表:

  • 它具有外键“ asset_id”,“ is_live”等。

  • asset_id已编入索引

  • 它有约5k行

2)'服务'表-一个简单的本地其他表:

  • 它具有主键'asset_id',该索引已被索引(以及其他一些列)
  • 它具有诸如“可用性”和“状态”之类的列
  • 它的值为'asset_owner'-
  • 的外键
  • 此表有约50,000行,该查询大部分不返回

3)'vw_people_Data'视图-一个包装远程表的视图:

  • vw_people_Data本质上是公正的(从our_people_table @ our_database_link中创建视图vw_people_Data作为select *)

  • 此表同时包含所有者和经理(以及其他所有人)

  • 此表有约80,000行,该查询大部分不返回

查询缓慢

此查询在约90秒内返回557行:

    SELECT * 
    FROM sales_leads leads
    LEFT OUTER JOIN services srvc ON (leads.asset_id = srvc.asset_id)
    LEFT OUTER JOIN 
      (
        SELECT 
            c.emp_id,
            c.display_name,
            c.primary_email_address,
            c.functional_manager_emp_id,
        FROM vw_people_Data c
      )m1 ON (m1.emp_id = srvc.asset_owner)
    LEFT OUTER JOIN 
      (
        SELECT 
            c.emp_id, 
            c.primary_email_address 
        FROM vw_people_Data c
      )m2 ON m1.functional_manager_emp_id = m2.emp_id

    WHERE srvc.availability like 'A%'
    AND srvc.status = 'true'
    AND leads.is_live like 'Live'
    ;

“快速”查询:

此查询在1.5秒内返回557行:

    SELECT * 
    FROM sales_leads leads
    LEFT OUTER JOIN services srvc ON (leads.asset_id = srvc.asset_id)
    LEFT OUTER JOIN 
          (
            SELECT 
              m1.emp_id m1_emp_id,
              m1.display_name m1_display_name,
              m1.primary_email_address m1_email,
              m2.emp_id m2_emp_id,
              m2.primary_email_address m2_email
            FROM vw_people_Data m1
            LEFT OUTER JOIN 
              (
                    SELECT 
                      c.emp_id,
                      c.primary_email_address
                    FROM vw_people_Data c
              ) m2 ON (m1.functional_manager_emp_id = m2.emp_id)
          ) m1_m2 ON (srvc.asset_owner = m1_m2.m1_emp_id)

    WHERE srvc.availability like 'A%'
    AND srvc.status = 'true'
    AND leads.is_live like 'Live'
    ;

问题:

为什么?为什么这么小的查询重写会大大缩短查询时间?优化器在做什么是那么不同?

我查看了执行计划,它们看起来相同。

1 个答案:

答案 0 :(得分:2)

在没有看到两个查询的解释计划的情况下进行调整的建议是杯子的游戏。但是,让我们猜一猜。

似乎关键在于:

  

唯一的视图是vw_people_Data,其定义为
  select *from tbl@our_db_link
  ................^

对查询的“次要” 更改是对该视图的访问路径的重新编写,该视图查询远程数据库上的表。跨数据库链接的性能调优联接非常棘手。基本上,远程数据库将其所有候选数据发送到本地数据库,在该数据库中评估联接并丢弃不匹配项。

在第一个查询中,远程视图上有两个子查询,因此您可以将两个结果远程发送到本地数据库。在第二个版本中,您有一个子查询,该子查询在远程数据库中应用联接。因此,发送到本地数据库的结果集要小得多,因为所有不匹配的vw_people记录都已被丢弃。