当前位置: 首页 > 面试题库 >

窗口功能SORT成本高昂,我们可以克服吗?

赫连靖琪
2023-03-14
问题内容

我的要求: 确定的前10个帐户,DEPT_NUM并按帐号升序排列。

询问:

SELECT * FROM
(
  select acctnum,dept_num,row_number() OVER (PARTITION BY DEPT_NUM ORDER BY ACCTNUM) as row_identifier
   FROM MYTABLE
)
WHERE row_identifier between 1 and 10;

痕迹:

    7532 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1480074522

--------------------------------------------------------------------------------------------
| Id  | Operation                | Name    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |         |   577K|    15M|       |  3855   (1)| 00:00:47 |
|*  1 |  VIEW                    |         |   577K|    15M|       |  3855   (1)| 00:00:47 |
|*  2 |   WINDOW SORT PUSHED RANK|         |   577K|  7890K|    13M|  3855   (1)| 00:00:47 |
|   3 |    INDEX FAST FULL SCAN  | IMTAB05 |   577K|  7890K|       |   987   (1)| 00:00:12 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("ROW_IDENTIFIER">=1 AND "ROW_IDENTIFIER"<=5)
   2 - filter(ROW_NUMBER() OVER ( PARTITION BY "DEPT_NUM" ORDER BY "ACCTNUM")<=5)


Statistics
----------------------------------------------------------
          0  recursive calls
          2  db block gets
       4298  consistent gets
          0  physical reads
          0  redo size
     144367  bytes sent via SQL*Net to client
        486  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
       7532  rows processed

指数:

index scan说,INDEX STORAGE在列DEPT_NUM

强制Full Table扫描的费用从3855降低至11092

表中的总行数为632667;

以上都是测试区域的结果。生产实际上是数量的两倍。

我的数据库是Exadata,Quarter RAC。运行Oracle 11g
R2。该数据库功能强大到可以立即执行,但是DBA不愿使用13M的tempSpc。商业报告该报告的频率将是每小时4次。最主要的是,该表获得了大量实时插入/更新

我们是否可以像
1)增加会话的PGA?(不确定,是否真的可能吗?)
2)附加索引有帮助吗?

只希望让其他人对此有所了解,因为我们小组完全专注于DBA参数。

感谢您的任何建议!


问题答案:

分析功能的性能可能取决于索引列的顺序。将索引从更改(ACCTNUM,DEPT_NUM)(DEPT_NUM,ACCTNUM)可以降低成本,并消除对临时表空间的需求。

partition by COL_2 order by COL_1 => INDEX FAST FULL SCAN|WINDOW SORT PUSHED RANK
partition by COL_1 order by COL_2 => INDEX FULL SCAN|WINDOW NOSORT

INDEX FAST FULL SCAN使用更快的多块IO,但它也需要对数据进行排序,并可能需要对排序区域进行临时表空间的排序。

INDEX FULL SCAN使用较慢的单块IO,但它按顺序返回数据并避免排序。

样本架构和数据

--drop table mytable;
create table mytable(dept_num number not null, acctnum number not null
    ,a number, b number, c number, d number, e number);
insert into mytable
select 1 dept_num, 1 acctnum, 0,0,0,0,0 from dual union all
select 1 dept_num, 2 acctnum, 0,0,0,0,0 from dual union all
select 1 dept_num, 3 acctnum, 0,0,0,0,0 from dual union all
select 2 dept_num, 1 acctnum, 0,0,0,0,0 from dual union all
select 2 dept_num, 2 acctnum, 0,0,0,0,0 from dual union all
select 3 dept_num, 1 acctnum, 0,0,0,0,0 from dual;
--Create 600K similar rows.
insert into mytable
  select dept_num + rownumber*3, acctnum, a,b,c,d,e
  from mytable
  cross join (select level rownumber from dual connect by level <= 100000);
begin
    dbms_stats.gather_table_stats(user, 'mytable');
end;
/

(ACCTNUM,DEPT_NUM)=窗口排序按排名

create index mytable_idx on mytable(acctnum, dept_num);

explain plan for
select dept_num, acctnum from
(
    select dept_num, acctnum
        ,row_number() over (partition by dept_num order by acctnum) as row_identifier
    from mytable
)
where row_identifier between 1 and 10;

select * from table(dbms_xplan.display);

Plan hash value: 952182109

------------------------------------------------------------------------------------------------
| Id  | Operation                | Name        | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |             |   600K|    22M|       |  1625   (3)| 00:00:23 |
|*  1 |  VIEW                    |             |   600K|    22M|       |  1625   (3)| 00:00:23 |
|*  2 |   WINDOW SORT PUSHED RANK|             |   600K|  4687K|  9424K|  1625   (3)| 00:00:23 |
|   3 |    INDEX FAST FULL SCAN  | MYTABLE_IDX |   600K|  4687K|       |   239   (3)| 00:00:04 |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("ROW_IDENTIFIER">=1 AND "ROW_IDENTIFIER"<=10)
   2 - filter(ROW_NUMBER() OVER ( PARTITION BY "DEPT_NUM" ORDER BY "ACCTNUM")<=10)

(DEPT_NUM,ACCTNUM)=窗口NOSORT

drop index mytable_idx;
create index mytable_idx on mytable(dept_num, acctnum);

explain plan for
select dept_num, acctnum from
(
    select dept_num, acctnum
        ,row_number() over (partition by dept_num order by acctnum) as row_identifier
    from mytable
)
where row_identifier between 1 and 10;

select * from table(dbms_xplan.display);

Plan hash value: 1773829932

---------------------------------------------------------------------------------
| Id  | Operation         | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |             |   600K|    22M|   792   (2)| 00:00:12 |
|*  1 |  VIEW             |             |   600K|    22M|   792   (2)| 00:00:12 |
|*  2 |   WINDOW NOSORT   |             |   600K|  4687K|   792   (2)| 00:00:12 |
|   3 |    INDEX FULL SCAN| MYTABLE_IDX |   600K|  4687K|   792   (2)| 00:00:12 |
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("ROW_IDENTIFIER">=1 AND "ROW_IDENTIFIER"<=10)
   2 - filter(ROW_NUMBER() OVER ( PARTITION BY "DEPT_NUM" ORDER BY 
              "ACCTNUM")<=10)


 类似资料:
  • 问题内容: 我需要让 我 部门中薪水最低的员工 使用反加入来做到。 但有人告诉我,可以通过 使用一次select的 window函数来做到这一点。但是我不能按department_id分组并同时使用它。那是虫子还是我愚蠢? SQL Developer说00979。00000-“不是GROUP BY表达式” 问题答案: 如果您运行第二个查询而没有(您可能已经尝试过)(从您发布的多余分号开始),您将看

  • 问题内容: 我正在尝试仅使用键盘来放大和缩小Chrome(seleniumwebdriver)。我努力了 - 但它不起作用。需要在python中回答。 问题答案: 我只是为此而苦苦挣扎。我设法找到了对我有用的东西,希望对您有用: 拥有’zoom%’=您想要的任何缩放级别。(例如“ 67%”)

  • 问题内容: 我正在探索Hive中的窗口功能,并且能够理解所有UDF的功能。虽然,我无法理解我们与其他功能配合使用的分区和顺序。以下是与我计划构建的查询非常相似的结构。 只是试图了解两个关键字都涉及的后台过程。 感谢帮助:) 问题答案: 分析函数为数据集中每个分区的每一行分配一个等级。 子句确定行的分布方式(如果是配置单元,则在缩减程序之间)。 确定行在分区中的排序方式。 第一阶段由分配 ,数据集中

  • 从下面的文章中我们知道,对于非键控流,并行度是1,那么我们可以通过setParallelism来增加并行度吗?如果是非键控流,原始流将不会被分割成多个逻辑流,所有窗口逻辑将由单个任务执行,即并行度为1 https://ci.apache.org/projects/flink/flink-docs-release-1.3/dev/windows.html#keyed-vs-non-keyed-win

  • 问题内容: 我使用java8创建了一个简单的接口。它包含一种方法和一种默认方法。 我正在尝试使用诸如 } 现在我正在尝试使用lambda表达式实现相同的功能,得到类似“ dummy is undefined”的错误。 谁能提出建议,如何使用Lambda表达式实现此方案? 问题答案: 不能做 JLS 15.27.2 解决了这个问题: 与出现在匿名类声明中的代码不同,名称的含义以及出现在lambda主

  • 问题内容: 我正在尝试编写一个程序,在其中我需要监视某些事件的未命名管道的末端。我可以使用具有轮询功能的未命名管道。 如果是,请您告诉我带有函数描述符的轮询函数的语法 问题答案: 投票的例子 要使用,如果要检查是否可读或可写: