oracle明确做排序

MK.*_*MK. 10 sql oracle

我在DISTINCT上表现不佳.解释计划表明它正在进行SORT(GROUP BY),听起来不对.我希望某种HASH聚合能产生更好的结果.是否有提示告诉oracle使用HASH进行DISTINCT而不是排序?我在类似情况下使用了/*+ USE_HASH_AGGREGATION*/,但它不适用于DISTINCT.

所以这是我原来的查询:

SELECT
count(distinct userid) n, col
FROM users
GROUP BY col;
Run Code Online (Sandbox Code Playgroud)

用户有30M行,每个用户ID有12次.此查询需要70秒.

现在我们将其重写为

SELECT
count(userid) n, col
FROM
(SELECT distinct userid, col FROM users)
GROUP BY col
Run Code Online (Sandbox Code Playgroud)

这需要40秒.现在添加提示来做hash而不是sort:

SELECT
count(userid) n, col
FROM
(SELECT /*+ USE_HASH_AGGREGATION */ distinct userid, col FROM users)
GROUP BY col
Run Code Online (Sandbox Code Playgroud)

这需要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|       |       |      |     |
Run Code Online (Sandbox Code Playgroud)

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|   |   |      |
--------------------------------------------------------------------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

小智 2

尝试以下操作怎么样:如果您在 col 和 userid 上有索引,它应该在索引中完全解析,并且根本不需要接触表。

Select count(userid) n, col
from (select col, userid from users group by col, userid)
group by col
;
Run Code Online (Sandbox Code Playgroud)