问题
My aim is to use a composite index on the student
table. The Student table will be inner joined onto the xyz
table. I created my index on the student table as follows:
CREATE INDEX email_phonenumber_student_idx
ON student(phonenumber, email);
When I run my query
SELECT Phonenumber, email from student
left join enrolment on enrolment.studentnumber = student.studentnumber
where months_between(SYSDATE, dateofbirth)/12 >= 18 and
enrolment.studentnumber is null and
student.phonenumber = '07123456788' and student.email = 'Chris@Lailasman.com’;
It works as intended, but the index is not being used as when I 'EXPLAIN PLAN FOR'
the query, I can only see the primary key as the index. Have I created the index on the wrong table? The issue arises is that I wanted to make use of a composite key, however, the joined table does not contain any columns for composite index use.
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1388008413
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 63 | 0 (0)| 00:00:01 |
| 1 | NESTED LOOPS ANTI | | 1 | 63 | 0 (0)| 00:00:01 |
|* 2 | TABLE ACCESS BY INDEX ROWID| STUDENT | 1 | 50 | 0 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | SYS_C0022463 | 1 | | 0 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | SYS_C0022468 | 1 | 13 | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("STUDENT"."EMAIL"='Chris@Lailasman.com' AND
MONTHS_BETWEEN(SYSDATE@!,INTERNAL_FUNCTION("STUDENT"."DATEOFBIRTH"))/12>=18)
3 - access("STUDENT"."PHONENUMBER"='07123456788')
4 - access("ENROLMENT"."STUDENTNUMBER"="STUDENT"."STUDENTNUMBER")
回答1:
Your estimated rows are "8". Indexes are not useful for such small tables. Oracle knows that so it just uses simpler scanning techniques.
There is an overhead to using indexes -- for instance, often both the index and the original data pages need to be read. They are useful as the data becomes larger.
回答2:
It works as expected. Oracle did exactly what you asked it to do.
CREATE INDEX email_phonenumber_student_idx
ON student(phonenumber, email);
You have a composite index on phonenumber, email
, while you do not use any of the columns in the filter predicate of your query:
where months_between(SYSDATE, dateofbirth)/12 >= 18
and xyz.studentnumber is null;
So there is no reason why Oracle would do an index scan on phonenumber, email
. You are simply SELECTing those columns of composite key, not filtering them:
SELECT Phonenumber, email
from student left join Xyz
Index will be used when you PROJECT those columns, not just SELECT. The STUDENT
table as expected goes for a FULL TABLE SCAN
as it is a plain select and doesn't use any filter on the indexed columns. If you want to see an index scan happening, then add below filter:
AND phonenumber = <value>
AND email = <value>
来源:https://stackoverflow.com/questions/61850728/can-i-have-a-composite-index-on-when-using-a-left-join