select po_number,
(select t.full_name
from person t
where t.subscriber_id=358
and t.company_id=2
and person_id=p.buyer_person_id) buyer_name
from po_header p
where subscriber_id=358 and company_id=2 ;
请看上面的例子。 伙计们,请你帮我理解select语句中的子查询性能吗?
答案 0 :(得分:1)
那么,有什么可说的?对于每个po_header,您将获得某个匹配人员的姓名。我们可以自然地想到循环:
但是我们已经知道,如果存在适当的索引,DBMS可能只是使用索引来查找名称而不是遍历person表。然而,不那么明显的是,DBMS可以完全自由地在内部重新编写查询。因此,DBMS可能做的第一件事就是加入两个表,然后删除它不需要的东西。或者它可以首先创建与公司和订户ID匹配的所有名称的列表,并在以后使用它进行查找。 DBMS有很多关于如何处理表的技术,Oracle的优化器非常好。
所以我们可能会猜到DBMS实际上做了什么,或者我们可能会看看执行计划。无论如何,这不是我们应该浪费太多时间的事情。如果查询运行良好而没有任何明显的性能问题,那么为什么要担心?一旦它显示查询 缓慢,我们就会查看执行计划并考虑要构建哪些索引,在这种情况下可能是这样的:
create index idx1 on po_header(subscriber_id, company_id, buyer_person_id, po_number);
create index idx2 on person(subscriber_id, company_id, person_id, full_name);
查询看起来很好并且可读且因此可维护。我认为没有理由改变它。那么,我们当然可以使相关性更清晰:
select
po_number,
(
select p.full_name
from person p
where p.subscriber_id = h.subscriber_id
and p.company_id = h.company_id
and p.person_id = h.buyer_person_id
) as buyer_name
from po_header h
where subscriber_id = 358 and company_id = 2;
答案 1 :(得分:0)
这是您当前的查询:
select po_number,
(select t.full_name from person t where t.subscriber_id=358 and
t.company_id=2 and person_id=p.buyer_person_id) buyer_name
from po_header p
where subscriber_id=358 and company_id=2;
SELECT
语句中的子查询是一种称为相关子查询的特定类型。此子查询的输出取决于外部查询或与外部查询相关。实际上,这意味着必须为po_header
表的每个记录运行子查询。从性能的角度来看,这可能代价高昂。
您所写的内容的替代方法是加入您的两个表,如下所示:
SELECT
p.po_number,
COALESCE(t.full_name, 'NA') AS full_name
FROM po_header p
LEFT JOIN person t
ON p.buyer_person_id = t.person_id AND
t.subscriber_id = 358 AND
t.company_id = 2
WHERE p.subscriber_id = 358 AND
p.company_id = 2
我希望这比原始查询执行得更好,特别是如果我们要为连接和WHERE
子句中涉及的列添加索引。