我的DISTINCT表现不佳。解释计划表明它正在进行SORT(GROUP BY),听起来不对。我希望某种HASH聚合能产生更好的结果。是否有提示告诉oracle使用HASH进行DISTINCT而不是排序? 我在类似情况下使用了/ * + USE_HASH_AGGREGATION * /,但它不适用于DISTINCT。
所以这是我原来的疑问:
SELECT
count(distinct userid) n, col
FROM users
GROUP BY col;
用户有30M行,每个用户ID有12次。此查询需要70秒。
现在我们将其重写为
SELECT
count(userid) n, col
FROM
(SELECT distinct userid, col FROM users)
GROUP BY col
需要40秒。 现在添加提示来执行hash而不是sort:
SELECT
count(userid) n, col
FROM
(SELECT /*+ USE_HASH_AGGREGATION */ distinct userid, col FROM users)
GROUP BY col
需要10秒钟。
如果有人可以向我解释为什么会发生这种情况,或者我如何能够将第一个简单的查询打造成与第3个一样好的工作,那就太棒了。
我关心查询简单性的原因是因为实际生成了这些查询。
计划: 1)慢:
----------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem | Used-Tmp|
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5 |00:01:12.01 | 283K| 292K| | | | |
| 1 | SORT GROUP BY | | 1 | 5 | 5 |00:01:12.01 | 283K| 292K| 194M| 448K| 172M (0)| 73728 |
| 2 | TABLE ACCESS FULL| USERS | 1 | 29M| 29M|00:00:08.17 | 283K| 283K| | | | |
2)快速
--------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem |
--------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 5 |00:00:13.09 | 283K| 283K| | | |
| 1 | SORT GROUP BY | | 1 | 5 | 5 |00:00:13.09 | 283K| 283K| 3072 | 3072 | 2048 (0)|
| 2 | VIEW | | 1 | 8647K| 2445K|00:00:13.16 | 283K| 283K| | | |
| 3 | HASH UNIQUE | | 1 | 8647K| 2445K|00:00:12.57 | 283K| 283K| 113M| 10M| 216M (0)|
| 4 | TABLE ACCESS FULL| USERS | 1 | 29M| 29M|00:00:07.68 | 283K| 283K| | | |
--------------------------------------------------------------------------------------------------------------------------------------------
答案 0 :(得分:2)
如何尝试以下方法: 如果您在col和userid上有索引,它应该在索引中完全解析,而不需要触摸该表。
Select count(userid) n, col
from (select col, userid from users group by col, userid)
group by col
;