【发布时间】:2018-08-31 11:14:23
【问题描述】:
我有一个查询需要大约 90 秒才能执行。以不同的方式稍微重写查询后,查询运行时间为 1.5 秒。你能解释为什么它运行得更快吗?
上下文
我有一个查询,它获取记录列表 - 将这些记录连接到资产列表,并将这些资产连接到人员列表,并将这些人员连接到另一个人员列表(他们的经理)。
为了便于说明,假设我们正在讨论一个新的销售线索列表,并且我们希望将这些线索加入到我们正在销售的服务中,以及这些服务的所有者和他们的经理.
表格
我们要从中提取 3 个对象:
1) 'sales_leads' 表 - 一个简单的本地表,只有一个索引:
它有外键“asset_id”和“is_live”等。
asset_id 已编入索引
它有大约 5k 行
2) 'services' 表 - 一个简单的、本地的其他东西表:
- 它有被索引的主键“asset_id”(以及其他一些列)
- 它有“可用性”和“状态”等列
- 它具有“asset_owner”的值 -
- 此表有大约 50,000 行,其中大部分此查询不会返回
3) 'vw_people_Data' 视图 - 包装远程表的视图:
vw_people_Data 本质上只是(创建视图 vw_people_Data 作为 select * from our_people_table@our_database_link)
此表同时包含所有者和管理者(以及其他所有人)
此表有大约 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'
;
问题:
为什么?为什么对查询进行如此小的重写会大大缩短查询时间?优化器在做什么如此不同?
我查看了执行计划,它们看起来一模一样。
【问题讨论】:
-
您需要查看执行计划来回答这个问题。当您使用没有定义的视图时,所有优化选项的赌注都将被取消。
-
@GordonLinoff 唯一的视图是定义为 select * from tbl@our_db_link 的 vw_people_Data ,如上所述
-
您可以使用提示 /*+ collect_plan_statistics */ 创建一个包含行源统计信息的计划,例如,获取一个具有实际执行时间的计划。这至少应该显示时间花在哪里。
-
这些时间是否可重复 - 或者第二个快速查询是否仅受益于第一个慢速查询执行期间缓存的数据?
-
顺便说一句:有时即使是相同的执行计划也可能会因为运行时引擎的决定而导致不同的性能。例如,用于全表扫描的
serial direct path access在计划中将不可见,但可能会导致执行速度更快或更慢(尽管问题并未表明这种差异可以解释给定情况下的某些问题)
标签: sql oracle relational-database sqlperformance