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

パフォーマンスの問題:selects。*とselect*の違い

    もちろん、これらは2つの異なるクエリです。プランは、選択が異なると変更できます。つまり、sth。*では、左側の結合テーブルでフル/高速フルインデックススキャンを選択している可能性があります。一方、最初は全表スキャンになる可能性があります。

    あなたをさらに助けるために、私たちは計画を見ることができますか?できればSQL*PLUSでこれを行ってください

    set timing on
    set autotrace on traceonly
    
    select s.* from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.sales_unit_child_id) where r.sales_unit_child_id is null;
    
    select * from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.sales_unit_child_id) where r.sales_unit_child_id is null;
    

    編集

    説明計画を考えると、すべてのステップでCARDINALITY =1が表示されますか?テーブルが空のときに統計を収集しました!これを参照してください:

    SQL> select s.* from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.child_sales_unit_id) where r.child_sales_unit_id is null;
    
    no rows selected
    
    Elapsed: 00:00:03.19
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 1064670292
    
    ------------------------------------------------------------------------------------
    | Id  | Operation          | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT   |               |     1 |    48 |    27  (86)| 00:00:01 |
    |   1 |  NESTED LOOPS ANTI |               |     1 |    48 |    27  (86)| 00:00:01 |
    |   2 |   TABLE ACCESS FULL| SALES_UNIT    |     1 |    35 |     2   (0)| 00:00:01 |
    |*  3 |   INDEX RANGE SCAN | SALES_REL_IX1 |     1 |    13 |    25  (92)| 00:00:01 |
    ------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       3 - access("S"."SALES_UNIT_ID"="R"."CHILD_SALES_UNIT_ID")
    
    
    Statistics
    ----------------------------------------------------------
              1  recursive calls
              0  db block gets
         200314  consistent gets
           2220  physical reads
              0  redo size
            297  bytes sent via SQL*Net to client
            339  bytes received via SQL*Net from client
              1  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              0  rows processed
    

    200314 IOを使用し、数秒かかったことを確認してください。また、すべてのステップでROWS =1を参照してください(つまり、フルスキャン)。統計を収集しましょう:

    SQL> begin dbms_stats.gather_table_stats(user, 'SALES_UNIT', degree=>8, cascade=>true); end;
      2  /
    
    PL/SQL procedure successfully completed.
    
    SQL> begin dbms_stats.gather_table_stats(user, 'SALES_UNIT_RELATION', degree=>8, cascade=>true); end;
      2  /
    
    PL/SQL procedure successfully completed.
    

    そして今、rerun:SQL>selects。*fromsales_unit s left join sales_unit_relation r on(s.sales_unit_id =r.child_sales_unit_id)where r.child_sales_unit_id is null;

    no rows selected
    
    Elapsed: 00:00:00.84
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2005864719
    
    -----------------------------------------------------------------------------------------------
    | Id  | Operation             | Name          | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT      |               |   912 | 18240 |       |  1659   (3)| 00:00:20 |
    |*  1 |  HASH JOIN ANTI       |               |   912 | 18240 |  2656K|  1659   (3)| 00:00:20 |
    |   2 |   TABLE ACCESS FULL   | SALES_UNIT    |   100K|  1472K|       |    88   (3)| 00:00:02 |
    |   3 |   INDEX FAST FULL SCAN| SALES_REL_IX1 |   991K|  4841K|       |   618   (3)| 00:00:08 |
    -----------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - access("S"."SALES_UNIT_ID"="R"."CHILD_SALES_UNIT_ID")
    
    
    Statistics
    ----------------------------------------------------------
              1  recursive calls
              0  db block gets
           2537  consistent gets
              0  physical reads
              0  redo size
            297  bytes sent via SQL*Net to client
            339  bytes received via SQL*Net from client
              1  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              0  rows processed
    
    SQL>
    

    現在、2537取得のみを使用しており、計画には適切なROWSとHASH結合が示されています(ニーズに適しています)。私のテストテーブルはおそらく実際のテーブルよりも小さいので、タイミングが近くなります




    1. PHPシリアル化関数-シリアル化されたデータをmysqlに追加してから、フェッチして表示します

    2. 多対多のテーブルMySQLを使用してフィルタリングする

    3. カスケード削除制約を追加するにはどうすればよいですか?

    4. pgAdminでユーザーを作成する方法