我有这样的查询...
SELECT cust_num, year,credit_cust FROM
(SELECT cust_num, year,credit_cust,
ROW_NUMBER () OVER(PARTITION BY cust_num, year ORDER BY credit_cust DESC) rnk
FROM credit_cust PARTITION (YEAR_2010)
)
WHERE rnk=1
执行此查询时,托管数据库的服务器的CPU使用率至少增加35%。当服务器中的负载很高时,这确实存在问题,因为有时CPU使用率达到100%。
要求:
数据如下......
Cust_num Year Credit_cust
456 2010 Y
456 2010 N
456 2009 N
456 2009 N
我希望查询只返回下面给出的记录......
Cust_num Year Credit_cust
456 2010 Y
456 2009 N
注意:我已使用ROW_NUMBER()作为GROUP BY子句的变通方法。因为,之前,我认为它只是导致CPU使用率高的GROUP BY子句
备用查询(其CPU使用率> 35%)
SELECT cust_num, YEAR, MAX (credit_cust)
FROM credit_cust PARTITION (year_2010)
GROUP BY cust_num, YEAR
Server : Sun OS 5.10
Database : Oracle 11g (11.2.0.2.0 -64bit)
credit_cust
表的结构如下......
CREATE TABLE CREDIT_CUST
(
CUST_NUM NUMBER,
YEAR NUMBER,
CREDIT_CUST CHAR(1)
)
TABLESPACE PARTITION_01
PARTITION BY RANGE (YEAR)
SUBPARTITION BY HASH (CUST_NUM)
(
PARTITION YEAR_2009 VALUES LESS THAN (2010)
SUBPARTITIONS 16 STORE IN (PARTITION_01,PARTITION_02,PARTITION_03,PARTITION_04,PARTITION_05,PARTITION_06,
PARTITION_01,PARTITION_02,PARTITION_03,PARTITION_04,PARTITION_05,PARTITION_06,
PARTITION_01,PARTITION_02,PARTITION_03,PARTITION_04),
PARTITION YEAR_2010 VALUES LESS THAN (2011)
SUBPARTITIONS 1 STORE IN (PARTITION_01))
PARALLEL ( DEGREE 16 INSTANCES 1 );
请告诉我为什么会出现这个问题。如果需要更多详细信息,请与我们联系。
EXPLAIN PLAN:
PLAN_TABLE_OUTPUT
Plan hash value: 3927595547
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 29M| 1179M| | 3937 (3)| 00:00:01 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10001 | 29M| 1179M| | 3937 (3)| 00:00:01 | | | Q1,01 | P->S | QC (RAND) |
|* 3 | VIEW | | 29M| 1179M| | 3937 (3)| 00:00:01 | | | Q1,01 | PCWP | |
|* 4 | WINDOW SORT PUSHED RANK | | 29M| 364M| 674M| 3937 (3)| 00:00:01 | | | Q1,01 | PCWP | |
| 5 | PX RECEIVE | | 29M| 364M| | 3937 (3)| 00:00:01 | | | Q1,01 | PCWP | |
| 6 | PX SEND HASH | :TQ10000 | 29M| 364M| | 3937 (3)| 00:00:01 | | | Q1,00 | P->P | HASH |
|* 7 | WINDOW CHILD PUSHED RANK| | 29M| 364M| | 3937 (3)| 00:00:01 | | | Q1,00 | PCWP | |
| 8 | PX BLOCK ITERATOR | | 29M| 364M| | 34 (3)| 00:00:01 | 1 | 1 | Q1,00 | PCWC | |
|* 9 | TABLE ACCESS FULL | CREDIT_CUST | 29M| 364M| | 34 (3)| 00:00:01 | 228 | 228 | Q1,00 | PCWP | |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("RNK"=1)
4 - filter(ROW_NUMBER() OVER ( PARTITION BY "CUST_NUM","YEAR" ORDER BY INTERNAL_FUNCTION("CREDIT_CUST") DESC )<=1)
7 - filter(ROW_NUMBER() OVER ( PARTITION BY "CUST_NUM","YEAR" ORDER BY INTERNAL_FUNCTION("CREDIT_CUST") DESC )<=1)
9 - filter("YEAR"=2010)
Note
-----
- dynamic sampling used for this statement (level=5)
答案 0 :(得分:1)
我有两点建议:
正确分区表格。你有一个subpartionion分区而另一个没有(一个子分区)。分区中的许多年份并不明显。我会使用Year的年度分区和cust上的哈希子分区(每个分区8或16个子分区。如果表格很大并且你有很多处理器,则使用16个。)
您的查询将在2007年,2008年,2009年,2010年返回客户的结果。您确定要四年吗?如果您只想要2010,则应在year = 2010
子句中指定where
,并且不需要在分析函数中按年分区,这有助于排序(消耗CPU和TEMP空间)。
查询将如下:
SELECT cust_num, year,credit_cust
FROM
(SELECT cust_num, year,credit_cust,
ROW_NUMBER () OVER(PARTITION BY cust_num ORDER BY credit_cust DESC) rnk
FROM credit_cust
WHERE YEAR=2010
)
WHERE rnk=1;
一般来说,最好选择带有where子句的分区而不是指定分区名称(也更容易)
答案 1 :(得分:0)
由于并行性,此查询使用大量CPU。该表格设置为DEGREE 16
。默认情况下,您的查询将使用16或32个并行服务器,具体取决于它们是否正在排序。
分区选项和查询执行计划在此处不直接相关。即使它们不正确,“坏”查询通常也不会每秒消耗大量资源。
有许多可能的解决方案,具体取决于您要禁用并行度的级别。以下是一些常见的解决方案:
/*+ no_parallel(credit_cust) */
alter session disable parallel query;
alter table cust parallel 1;
alter system set parallel_max_servers = 0;
但在改变任何事情之前要仔细考虑。如果使用不当,其中一些解决方案可能是灾难性的。您需要很好地理解并行性,系统资源以及系统的使用方式。像往常一样,一个好的起点是manual。