什么是快乐星球?什么又是“标量子查询”呢?
Posted bisal
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是快乐星球?什么又是“标量子查询”呢?相关的知识,希望对你有一定的参考价值。
现在有个很火的歌词,“什么是快乐星球?”,那个劲儿,其实还很难拿捏,
同理地,以前总是在资料或者培训中听到“标量子查询”,好像很神秘的一个概念,什么是“标量子查询”?
其实从形式上讲,标量子查询就是在查询语句select和from之间的子查询,这就决定了他的返回值肯定只能是1条,如果是多条,就可能提示“ORA-01427:单行子查询返回多个行的错误”。
这是一个标量子查询的例子,
SQL> select /*+ gather_plan_statistics */ e.first_name, e.salary,
(select d.department_name from departments d
where d.department_id = e.department_id) d_name
from employees e;
他的执行计划,
从执行计划,可以看到,主表employees通过连接列(department_id)传值给子查询中的表(departments),上述执行计划中第二步的* - :B1就是传值,而且传值12次。
之所以是12次,因为主表的连接列基数是12,
SQL> select count(distinct nvl(department_id,0)) from employees;
COUNT(DISTINCTNVL(DEPARTMENT_ID,0))
-----------------------------------
12
从这个过程,我们能知道,如果必须使用标量子查询,要为子查询的连接列创建索引,毕竟主表连接列基数是多少,子查询就会被执行多少次,因此能推导出,如果主表的数据量很少,或者主表的连接列基数很低,子查询的连接列创建了索引,是可以使用标量子查询的。反之,主表返回的数据量很多,主表的连接列基数很高,甚至子查询的连接列没索引,应该避免使用标量子查询。
为了避免使用标量子查询,一般可以改写为外连接,
SQL> select /*+ gather_plan_statistics */ e.first_name, e.salary, d.department_name
from employees e
left join departments d
on e.department_id = d.department_id;
他的执行计划,
可以看到,原来的子查询改为了全表扫描,但是仅需要扫描一次,和主表做哈希外连接。
之所以是外连接,因为每次主表传值给子查询,但未必在子查询中就存在对应的记录,但是如果子查询的连接列就是主表的外键,或者业务上就是1:1的关系(这里用到了落落老师在培训和书中提到的数量关系),外连接可以改为内连接,他俩是等价的,如本例中,employees共107条,
SQL> select count(*) from employees;
COUNT(*)
----------
107
如果采用外连接,返回107条,
SQL> select count(*) from employees e left join departments d on e.department_id = d.department_id;
COUNT(*)
----------
107
如果采用内连接,只会返回106条,说明在employees中有一条记录在departments是找不到的,
SQL> select count(*) from employees e join departments d on e.department_id = d.department_id;
COUNT(*)
----------
106
这个例子中,标量子查询departments和主表employees是1:N的关系,因此改为外连接的时候,不需要去重。
如果是这种,标量子查询和主表是N:1的关系,
SQL> select d.department_name,
(select max(e.salary) from employees e where e.department_id = d.department_id) max_salary
from departments d;
DEPARTMENT_NAME MAX_SALARY
--------------------- ----------
Shipping 8200
Human Resources 6500
Accounting 12008
Executive 24000
Purchasing 11000
Public Relations 10000
Administration 4400
Marketing 13000
IT 9000
Finance 12008
Sales 14000
IT Support
Operations
Payroll
Construction
Government Sales
Retail Sales
Contracting
Recruiting
Control And Credit
NOC
Treasury
Manufacturing
Corporate Tax
IT Helpdesk
Shareholder Services
Benefits
27 rows selected.
改成外连接,需要对标量子查询做去重(group by),可以先去重,再做关联,如下所示,
SQL> select /*+ gather_plan_statistics */ d.department_name, max_salary
from departments d
left join (select max(salary) max_salary, department_id from employees group by department_id) e
on e.department_id = d.department_id;
DEPARTMENT_NAME MAX_SALARY
---------------------- ----------
Shipping 8200
Human Resources 6500
Accounting 12008
Executive 24000
Purchasing 11000
Public Relations 10000
Administration 4400
Marketing 13000
IT 9000
Finance 12008
Sales 14000
IT Support
Operations
Payroll
Construction
Government Sales
Retail Sales
Contracting
Recruiting
Control And Credit
NOC
Treasury
Manufacturing
Corporate Tax
IT Helpdesk
Shareholder Services
Benefits
27 rows selected.
他的执行计划,
或者先关联,再做去重,如下所示,
SQL> select /*+ gather_plan_statistics */ d.department_name, max(e.salary)
from departments d
left join employees e
on e.department_id = d.department_id
group by d.department_name;
DEPARTMENT_NAME MAX(E.SALARY)
--------------------- -------------
Sales 14000
Recruiting
Control And Credit
IT Support
Government Sales
Retail Sales
Corporate Tax
Marketing 13000
IT Helpdesk
Purchasing 11000
Administration 4400
Contracting
NOC
Executive 24000
IT 9000
Finance 12008
Shipping 8200
Public Relations 10000
Payroll
Shareholder Services
Benefits
Human Resources 6500
Accounting 12008
Operations
Construction
Treasury
Manufacturing
27 rows selected.
他的执行计划,
从执行计划看,这两种写法,成本几乎相同。
理解标量子查询的适用场景,以及改成外连接是否需要去重的意义,是对待这种标量子查询的关键。
近期更新的文章:
文章分类和索引:
以上是关于什么是快乐星球?什么又是“标量子查询”呢?的主要内容,如果未能解决你的问题,请参考以下文章