我想知道下面的兩個查詢是否有區別。
我正在尋找一個一般性的答案,以解釋優化器如何處理這些答案中的每一個。在t.id.上有一個索引。
Oracle的版本是11g。
select t.id, sum(t.mount)
from交易t
group by t.id
having sum(t.amount) between 0. 009 and 0.009 0.
select t.id, sum(t.quantity)
from交易t
group by t.id
having sum(t.amount) >= -0。 009 and sum(t.amount)<= 0.009
uj5u.com熱心網友回復:
在聚合查詢中,大部分的作業涉及到資料的移動。 聚合有一定的開銷,但通常非常簡單。
而且,SQL 編譯器可以決定它是否要重新使用聚合運算式。 僅僅因為您在查詢中使用了sum(amount)兩次,并不意味著它被執行兩次。
一些聚合函式是更昂貴的 -- 特別是在字串上或使用distinct。 你可以隨時測驗查詢,看看是否有很大的影響,但一般來說,你應該擔心你的邏輯是否正確,而不是你使用聚合函式的次數。
uj5u.com熱心網友回復:
如果你想了解CBO決定執行SQL陳述句的步驟的基本資訊,請使用explain plan
例子
EXPLAIN PLAN SET STATEMENT_ID = 'jara1' into plan_table FOR
select DEPARTMENT_ID, sum(工資)
from HR.employees
group by DEPARTMENT_ID
having sum(salary) 介于 5000 and 10000之間
;
--
SELECT * FROM table(DBMS_XPLAN. DISPLAY('plan_table', 'jara1','ALL'))。)
查詢的結果是
Plan hash value。244580604
---------------------------------------------------------------------------------
| Id | 操作 | 名稱 | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 4 (25)| 00: 00:01 |
|* 1 | FILTER | | | | | |
| 2 | HASH GROUP BY | | 1 | 7 | 4 (25)| 00: 00:01 |
| 3 | TABLE ACCESS FULL| EMPLOYEES | 107 | 749 | 3 (0)| 00: 00:01 |
---------------------------------------------------------------------------------
查詢塊名稱 / 物件別名(通過操作ID識別)。
-------------------------------------------------------------
1 - SEL$1
3 - SEL$1 / EMPLOYEES@SEL$1
謂語資訊(通過操作ID識別)。
---------------------------------------------------
1 - filter(SUM("SALARY")>。 =5000 AND SUM("SALARY")<=10000)
列預測資訊(通過操作ID識別)。
-----------------------------------------------------------
1 - (rowset=256) "DEPARTMENT_ID"[NUMBER,22], SUM("SALARY") [22]
2 - (#keys=1; rowset=256) "DEPARTMENT_ID"[NUMBER,22] 。
SUM("SALARY")[22]。
3 - (rowset=256) "SALARY"[NUMBER,22], "DEPARTMENT_ID"[NUMBER,22]
所以首先你看到一個TABLE ACCESS FULL被執行(第3行),所以你的索引假設是不正確的。
正如其他答案所指出的,你看到between被翻譯成兩個與and相連的perdicates(過濾行1)。
但對你的問題最重要的是列投影,你看到sum(SALARY)是在第2行(HASH GROUP BY操作)計算的,并傳遞到第1行(FILTER),在這兩種情況下只有一次(一列長度為22)。
所以不用擔心多重計算。
uj5u.com熱心網友回復:
這兩個查詢之間絕對沒有區別。between只是語法上的糖;決議器立即將between條件轉化為兩個不等式,并與and運算子相結合。這甚至在優化器看到該查詢之前就已經完成了。(請注意,在這種情況下,決議和優化階段之間的區別是有意義的,盡管程式員通常認為它們是一個步驟。
微不足道的例子:
SQL> set autotrace traceonly explain
SQL> select deptno, sum(sal) as sum_sal
2 from scott.emp
3 group by deptno
4 having sum(sal)介于 10000 and 20000
5 ;
執行計劃
----------------------------------------------------------
計劃哈希值。2138686577
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 4 (25)| 00: 00:01 |
|* 1 | FILTER | | | | | |
| 2 | HASH GROUP BY | | 1 | 7 | 4 (25)| 00: 00:01 |
| 3 | TABLE ACCESS FULL| EMP | 14 | 98 | 3 (0)| 00: 00:01 |
----------------------------------------------------------------------------
謂語資訊(通過操作ID識別)。
---------------------------------------------------
1 - filter(SUM("SAL")> =10000 AND SUM( "SAL")<=20000)
你提到的 "索引在...... "的事情與問題無關。
uj5u.com熱心網友回復:
另一種有趣的方法來測驗這個問題:
with function expand_sql_text(text_in varchar2)
return varchar2
as
text_out長。
begin
dbms_utility.expand_sql_text(text_in, text_out)。
return text_out;
end expand_sql_text。
select expand_sql_text(
'select * from dual where 2 between 1 and 3'
) as text_out
from dual
/
TEXT_OUT
------------------------------------------------------------------------------------------------------------------------------------------------------------
選擇 "a1". "dummy" "dummy" FROM "SYS". "DUAL" "A1" WHERE 2>=1 AND 2<=3
選擇了1行。
在你原來的問題中,第二個謂詞是
having sum(t.quantity) > -0. 009 and sum(t.amount)</span> 0.009
這與between版本不一樣,因為between并不是排他性的。
在 SQL 中,針對簡單字面的過濾謂詞通常不會導致任何顯著的性能開銷。在 group by 子句中,在聚合之后應用謂詞的事實進一步減少了任何開銷。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/332033.html
標籤:
