我遇到了一个我无法理解的性能问题。我正在执行的查询如下:
SELECT UNIQUE GROUP_ID
FROM pos, TABLE (t_type(12984918, 12984919, 12984917))
WHERE pos.pos_id = COLUMN_VALUE AND GROUP_ID <> 0;
1 row returned in 99 ms
你可能认为83毫秒没问题,但令我感到困惑的是,即使只有3个重复值,删除UNIQUE
也会使查询更快:
SELECT GROUP_ID
FROM pos, TABLE (t_type(12984918, 12984919, 12984917))
WHERE pos.pos_id = COLUMN_VALUE AND GROUP_ID <> 0;
3 rows returned in 0.048 ms
oracle真的需要花费近100毫秒来将一组3个元素减少为单个值吗?这对我来说似乎很疯狂,所以我开始做一些调查并用TKPROF
获取执行计划。
SELECT UNIQUE GROUP_ID
FROM pos, TABLE (t_type(12984918, 12984919, 12984917))
WHERE pos.pos_id = COLUMN_VALUE AND GROUP_ID <> 0
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 2 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.00 0.09 0 8 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.10 0 10 0 1
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 58
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
1 1 1 HASH UNIQUE (cr=8 pr=0 pw=0 time=99258 us cost=31 size=3892 card=139)
3 3 3 NESTED LOOPS (cr=8 pr=0 pw=0 time=84 us)
3 3 3 NESTED LOOPS (cr=5 pr=0 pw=0 time=59 us cost=30 size=3892 card=139)
3 3 3 COLLECTION ITERATOR CONSTRUCTOR FETCH (cr=0 pr=0 pw=0 time=7 us cost=29 size=16336 card=8168)
3 3 3 INDEX UNIQUE SCAN IU_POS_POS_ID (cr=5 pr=0 pw=0 time=31 us cost=0 size=0 card=1)(object id 20684)
3 3 3 TABLE ACCESS BY INDEX ROWID POS (cr=3 pr=0 pw=0 time=12 us cost=0 size=26 card=1)
嗯,使用HASH UNIQUE
操作,Oracle看起来真的需要99毫秒才能将3个相同的值减少到一个值。实际上,STILL似乎很疯狂。这几乎不应该引人注意。所以我开始寻找替代方案。事实证明,Oracle也可以使用SORT UNIQUE
操作来实现DISTINCT
。我还发现我可以通过执行以下操作强制oracle不使用HASH UNIQUE
:
ALTER SESSION SET "_gby_hash_aggregation_enabled" = true;
现在,我的查询运行时间为0.48毫秒!这是一个2000倍的改进! WTF!以下是使用SORT UNIQUE
显示的执行计划:
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 2 0.00 0.00 0 4 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 16 0 2
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 6 0.00 0.00 0 20 0 2
Misses in library cache during parse: 2
Optimizer mode: ALL_ROWS
Parsing user id: 58
Number of plan statistics captured: 2
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
1 1 1 SORT UNIQUE (cr=8 pr=0 pw=0 time=48 us cost=30 size=28 card=1)
3 3 3 NESTED LOOPS (cr=8 pr=0 pw=0 time=35 us)
3 3 3 NESTED LOOPS (cr=5 pr=0 pw=0 time=26 us cost=29 size=28 card=1)
3 3 3 COLLECTION ITERATOR CONSTRUCTOR FETCH (cr=0 pr=0 pw=0 time=2 us cost=29 size=6 card=3)
3 3 3 INDEX UNIQUE SCAN IU_POS_POS_ID (cr=5 pr=0 pw=0 time=17 us cost=0 size=0 card=1)(object id 20684)
3 3 3 TABLE ACCESS BY INDEX ROWID POS (cr=3 pr=0 pw=0 time=7 us cost=0 size=26 card=1)
********************************************************************************
好的,现在我正在思考如何在不触及会话参数的情况下强制oracle使用SORT UNIQUE。事实证明我可以添加一个ORDER BY
子句,并加快我的查询速度。
SELECT UNIQUE GROUP_ID
FROM pos, TABLE (t_type(12984918, 12984919, 12984917))
WHERE pos.pos_id = COLUMN_VALUE AND GROUP_ID <> 0
ORDER BY GROUP_ID;
所以基本上我已经解决了我的问题(如果你可以称之为那种黑客&#34;解决问题&#34;),但我仍然感到困惑。
以下是问题:
HASH UNIQUE
而不是SORT UNIQUE
?HASH UNIQUE
这么慢? SORT UNIQUE
而不是HASH UNIQUE
?答案 0 :(得分:2)
为什么Oracle选择HASH UNIQUE而非SORT UNIQUE?
您的第一个tkprof结果显示TABLE
迭代器的基数高得多(预期?)。 Oracle正在针对超过三行进行优化。
当只有3条记录要哈希时,为什么HASH UNIQUE这么慢?
Hash unique将需要构建一个哈希表,无论有多少元素被哈希化。据推测,对于较少的元素,哈希表的大小会更小,但基数估计值也是如此,以至于Oracle将构建更大的哈希表。
有没有更好的方法来暗示oracle在HASH UNIQUE上使用SORT UNIQUE?
我会尝试在表格操作符上暗示基数。
答案 1 :(得分:0)
有没有更好的方法来暗示oracle在HASH上使用SORT UNIQUE UNIQUE?
我会检查如何收集表和索引统计信息。它们由oracle优化器使用,以便构建有效的访问计划。