sql >> Database >  >> RDS >> Oracle

Uitvoeringsvolgorde van voorwaarden in SQL 'where'-clausule

Weet je het zeker u "niet de bevoegdheid" heeft om een ​​uitvoeringsplan in te zien? Hoe zit het met het gebruik van AUTOTRACE?

SQL> set autotrace on
SQL> select * from emp
  2  join dept on dept.deptno = emp.deptno
  3  where emp.ename like 'K%'
  4  and dept.loc like 'l%'
  5  /

no rows selected


Execution Plan
----------------------------------------------------------

----------------------------------------------------------------------------------
| Id  | Operation                    | Name         | Rows  | Bytes | Cost (%CPU)|
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |              |     1 |    62 |     4   (0)|
|   1 |  NESTED LOOPS                |              |     1 |    62 |     4   (0)|
|*  2 |   TABLE ACCESS FULL          | EMP          |     1 |    42 |     3   (0)|
|*  3 |   TABLE ACCESS BY INDEX ROWID| DEPT         |     1 |    20 |     1   (0)|
|*  4 |    INDEX UNIQUE SCAN         | SYS_C0042912 |     1 |       |     0   (0)|
----------------------------------------------------------------------------------

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

   2 - filter("EMP"."ENAME" LIKE 'K%' AND "EMP"."DEPTNO" IS NOT NULL)
   3 - filter("DEPT"."LOC" LIKE 'l%')
   4 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")

Zoals je kunt zien, geeft dat behoorlijk veel details over hoe de query zal worden uitgevoerd. Het vertelt me ​​dat:

  • de voorwaarde "emp.ename like 'K%'" wordt als eerste toegepast op de volledige scan van EMP
  • dan worden de overeenkomende DEPT-records geselecteerd via de index op dept.deptno (via de NESTED LOOPS-methode)
  • eindelijk wordt het filter "dept.loc zoals 'l%' toegepast.

Deze volgorde van aanbrengen heeft niets te maken met de manier waarop de predikaten zijn geordend in de WHERE-clausule, zoals we kunnen aantonen met deze opnieuw geordende zoekopdracht:

SQL> select * from emp
  2  join dept on dept.deptno = emp.deptno
  3  where dept.loc like 'l%'
  4  and emp.ename like 'K%';

no rows selected


Execution Plan
----------------------------------------------------------

----------------------------------------------------------------------------------
| Id  | Operation                    | Name         | Rows  | Bytes | Cost (%CPU)|
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |              |     1 |    62 |     4   (0)|
|   1 |  NESTED LOOPS                |              |     1 |    62 |     4   (0)|
|*  2 |   TABLE ACCESS FULL          | EMP          |     1 |    42 |     3   (0)|
|*  3 |   TABLE ACCESS BY INDEX ROWID| DEPT         |     1 |    20 |     1   (0)|
|*  4 |    INDEX UNIQUE SCAN         | SYS_C0042912 |     1 |       |     0   (0)|
----------------------------------------------------------------------------------

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

   2 - filter("EMP"."ENAME" LIKE 'K%' AND "EMP"."DEPTNO" IS NOT NULL)
   3 - filter("DEPT"."LOC" LIKE 'l%')
   4 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")


  1. Slechte gewoonten:alleen focussen op schijfruimte bij het kiezen van sleutels

  2. biginteger array-functies

  3. Hoe bepaal ik wanneer ik rechter joins/links joins of inner joins moet gebruiken Of hoe bepaal ik welke tafel aan welke kant staat?

  4. Hoe te selecteren met behulp van de WITH RECURSIVE-clausule