بهبود کارایی UNION – UNION All در اوراکل
هنگام استفاده از UNION در اوراکل در صورتيكه در هر كدام از كوئريها ركورد تكراري وجود داشته باشد فقط يك ركورد از آن ركوردهاي تكراري با كوئري دوم جمع بسته مي شود.
بدين صورت است :
DISTINCT(DISTINCT (Q1) + DISTINCT (Q2)) = DISTINCT(Q1 + Q2)
هنگام استفاده از UNION ALL در اوراکل كل ركوردهاي كوئري اول با كل ركوردهاي كوئري دوم جمع بسته مي شود
بدين صورت است :
Q1 + Q2
به کوئری زیر توجه کنید: اشاره می شود که حتما باید یکطرف مقدار Not Null داشته باشد. چون کوئری زیر بی معنی می باشد
SELECT NULL FROM DUAL UNION SELECT NULL FROM DUAL
Result:
-
Result:
-
SELECT NULL FROM DUAL UNION ALL SELECT NULL FROM DUAL
Result:
-
-
Result:
-
-
درباره UNION Performance در اوراکل
در خصوص UNION در Oracle: بسیار بهینه سازی شده و واقعا سریع مي باشد به جز در مواردی که یکی از كوئري ها در زمان طولانی قبل از دیگر كوئري ها تمام شده باشد، و اوراکل باید تا بدست آوردن تمام نتیجه مجموعه قبل از شروع مرتب سازی صبر كند.
چندين جايگزيني براي عملگر Union SQL در اوراکل وجود دارد:
-
استفاده از UNION ALL : ممكن است سريعتر باشد زماني كه در خروجي ركورد تكراري وجود نداشته باشد
-
اجرا كردن هر كوئري بصورت جداگانه و تركيب كردن و مرتب سازي درون برنامه خودتان.
-
بعضي اوقات مرتب سازي بيروني ممكن است باعث افزايش سرعت شود.
-
استفاده ازjoin جداول بصورت دستي، كند و ناكارامد مي باشد.
-
در نسخه Oracle 11.2 بهينه ساز SQL بهبود يافته و براي UNION ALL از Join Factorization transformation مخفف -JFT- استفاده مي كند.
-
با استفاده از نمايش كوئري ها در in-line كارائي بهبود بخشيده مي شود.
به مثال زیر توجه کنید:
Q1:
select e1.empno, e2.deptno, e2.dname
from emp e1, dept e2
where e1.deptno = e2.deptno
Union All
select e1.empno, e2.deptno, e2.dname
from emp e1, dept e2
where e1.deptno = e2.deptno
Q1:
select e1.empno, e2.deptno, e2.dname
from emp e1, dept e2
where e1.deptno = e2.deptno
Union All
select e1.empno, e2.deptno, e2.dname
from emp e1, dept e2
where e1.deptno = e2.deptno
حال اگر emp خيلي بزرگ باشد از يك اسكن بزرگ جلوگيري مي شود و باعث بهبود عملكرد می گردد.
Q2:in-line
select e1.empno, vw_join.deptno, vw_join.dname
from emp e1, (
select e1.empno, e2.deptno, e2.dname
from emp e1, dept e2
where e1.deptno = e2.deptno
Union All
select e1.empno, e2.deptno, e2.dname
from emp e1, dept e2
where e1.deptno = e2.deptno
) vw_join
where e1.empno = vw_join.empno
select e1.empno, vw_join.deptno, vw_join.dname
from emp e1, (
select e1.empno, e2.deptno, e2.dname
from emp e1, dept e2
where e1.deptno = e2.deptno
Union All
select e1.empno, e2.deptno, e2.dname
from emp e1, dept e2
where e1.deptno = e2.deptno
) vw_join
where e1.empno = vw_join.empno
استفاده از FULL OUTER JOIN with the NVL function به جاي UNION، به نظر مي رسد كه داراي عملكرد سريعتري نسبت به UNION مي باشد.
Q:
select
empno,
ename,
nvl(dept.deptno,emp.deptno) deptno, dname
from
test.emp
full outer join test.dept
on (emp.deptno = dept.deptno) order by 1,2,3,4
select
empno,
ename,
nvl(dept.deptno,emp.deptno) deptno, dname
from
test.emp
full outer join test.dept
on (emp.deptno = dept.deptno) order by 1,2,3,4
نکته:
وقتي شما UNION يا UNION ALL را جايگزين مي كنيد:
-
اولا بايد با ” Execution Plan” آنرا در اوراکل مقايسه كنيد.
-
دوما بايد با استفاده از SQL*PLUS در اوراکل و فعال كردن set timing on زمان واقعي اجرا را نيز با هم مقايسه كنيد.