原文作者:Jonathan lewis
原文地址:https://jonathanlewis.wordpress.com/2010/01/26/aliases/
Aliases
— Jonathan Lewis @ 6:45 pm GMT Jan 26,2010
最近有人问我以下问题:“使用表别名会影响性能吗?”对于这个问题,最好的回答可能是“是的,但是一般来说,你可能不会注意到区别,使用表别名有远比性能更重要的原因。”
思考以下两个版本的简单SQL语句:
select
s.name,
c.title
from
du_course c,
du_student s
where
c.start_year = 2009
and s.student_id = c.student_id
;
--
--
select
du_student.name,
du_course.title
from
du_course,
du_student
where
du_course.start_year = 2009
and du_student.student_id = du_course.student_id
;
首先要注意的是,我们需要在这个语句中至少限定一些列名,因为student_id出现在两个不同的表中。在你写的所有SQL中限定列的非常重要的原因是多个表用相同列名—如果你不习惯这样做,你将最终落入“column capture”陷阱之中,(例如)一个子查询中的表包含了主查询中的一列,然后优化器往你不希望的方向解析了那列。
但是,如果你限定了“有风险”的列名,你不限定其余列名有关系吗?在分析任何SQL语句时,Oracle必须做的第一件事是检查所引用的列是否合法,因此必须说:“这是tableA中的columnX,这是tableB中的columnX”,等等。如果不限定列,则可能必须对照查询中的每个表检查每个列-如果你限定它们,则只需对限定符标识的表检查每一列。因此,在大多数情况下,通过限定列,你将节省一点CPU资源…这可能是你从限定列名中获得的唯一的性能提升。不过,与语句所做的其他工作相比,节省的CPU量很可能很小,因此如果你只关心性能,那么你可能不会为了确保列名被适当限定而小题大做。
但是,限定所有列名还有另一个好处—而不仅仅是“有风险”的列名。它使下一个人更容易理解和调试SQL。
就像没有限定词会(稍微)降低优化器的速度一样,它也会(显著地)降低人类读者的速度。假设你想要调试的SQL连接七张表,包括引用到的45个列名—它需要你付出多少精力来理解一个谓词如:“and cancellation_date > delivery_date”,并且推断出这是不是那个建议对索引定义做个改变,或给SQL添加个额外的hint的谓词。你甚至可能会注意到,select列表中只有来自特定表的一列,并考虑将该列添加到用于连接的索引中。如果你立即知道每个列属于哪个表,因为它的名称是限定的,那么事情不是会更简单吗?所以一定要限定列名—这有助于使代码更安全、更易于阅读,即使你可能不会注意到任何性能上的好处。
唯一重要的问题是:“确定列名的最佳策略是什么?”到目前为止,我已经给出了两个选项,但我都不喜欢。单个字母别名使用的CPU略少于完整的表名—但这也是一种不必要的节省,特别是当语句开始变得复杂时,单个字母别名并不能真正帮助你记住表名。另一方面,使用完整的表名可能会使SQL非常难于阅读—特别是如果你的标准包括模式名,并将所有内容都用大写字母表示。
(最坏的情况—每个table_name都包含模式名的一部分,每个列名都包含table_name的一部分,所有代码都是大写的。大约80%的SQL语句是schema和table_name的重复;具有完全限定的列如下:dw_stage . dw_stg_transactions . dw_stg_trans_transaction_id)。
我的指导原则是:为查询中的每个表提供三个(或四个)字母别名,但要保持一致,以提示完整的表名。如果在同一个查询中多次使用同一个表,那么在每种情况下都要向别名添加一个数字。因此,表order可能是ord,而order_lines变成orl。其思想是在限定符中保留足够的文本以提醒读者源表的名称,但是不要保留太多的文本,以至于你用大量的限定词淹没了语句。
在遵循指导原则时,我的小样本没有太大的变化,但这是我选择写的东西:
select
stu.name,
crs.title
from
du_course crs,
du_student stu
where
crs.start_year = 2009
and stu.student_id = crs.student_id




