sql >> データベース >  >> RDS >> Oracle

ウィンドウ関数はSORTコストがかかりますが、それを克服できますか?

    分析関数のパフォーマンスは、インデックス列の順序に依存する場合があります。 (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)=WINDOW 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)
    



    1. MySQLGROUPBYの動作

    2. SQLite-テーブルをドロップ

    3. Laravel:指定されたキーが長すぎました。キーの最大長は767バイトです

    4. MySQLDATE_ADDが機能しない