使用左连接时无法建立复合索引
Unable to have a composite index on when using a left join
我的目标是对学生 table 使用复合索引。学生 table 将被内部加入到注册 table 中。我在学生 table 上创建了如下索引:
CREATE INDEX email_phonenumber_student_idx
ON student(phonenumber, email);
当我运行我的查询
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’;
它按预期工作,但是当我 'EXPLAIN PLAN FOR' 查询时索引没有被使用,我只能看到主键作为索引。我是否在错误的 table 上创建了索引?出现的问题是我想使用复合键,但是,连接的 table 不包含任何用于复合索引的列。
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")
explain
显示优化器在给定当前 "shape"(大小、分布等)数据的情况下实际执行的操作。
数据库最昂贵的操作是磁盘 I/O。由于您只有 17 行,因此整个 table 可能会通过单个 I/O 操作(通常是 2K 页)读入内存,因此将整个 table 读入内存会更快并扫描内存中的所有行而不是通过索引,这将需要多次 I/O 操作。
您可能会发现索引在大约 1000 行处开始使用,但这取决于您的架构。
我的目标是对学生 table 使用复合索引。学生 table 将被内部加入到注册 table 中。我在学生 table 上创建了如下索引:
CREATE INDEX email_phonenumber_student_idx
ON student(phonenumber, email);
当我运行我的查询
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’;
它按预期工作,但是当我 'EXPLAIN PLAN FOR' 查询时索引没有被使用,我只能看到主键作为索引。我是否在错误的 table 上创建了索引?出现的问题是我想使用复合键,但是,连接的 table 不包含任何用于复合索引的列。
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")
explain
显示优化器在给定当前 "shape"(大小、分布等)数据的情况下实际执行的操作。
数据库最昂贵的操作是磁盘 I/O。由于您只有 17 行,因此整个 table 可能会通过单个 I/O 操作(通常是 2K 页)读入内存,因此将整个 table 读入内存会更快并扫描内存中的所有行而不是通过索引,这将需要多次 I/O 操作。
您可能会发现索引在大约 1000 行处开始使用,但这取决于您的架构。