Oracle sql 查询计划不将索引与 or 语句和子查询一起使用
Oracle sql query plan does not uses indices with or statement and a subquery
我有一个包含 'or' 语句和 'inner select' 语句的查询。当我检查查询计划时,它使用完全 table 访问权限,我不知道为什么会这样。
我创建了这个测试用例来说明我的问题:
CREATE TABLE PERSON (
ID NUMBER(18) NOT NULL,
NAME VARCHAR2(18) NOT NULL,
SURNAME VARCHAR2(18) NOT NULL
);
BEGIN
FOR b IN 1..500000
LOOP
INSERT INTO PERSON VALUES (b,'name' || to_char(b),'surname' || to_char(b));
END LOOP;
END;
CREATE INDEX PERSON_NAME_index ON PERSON(NAME);
CREATE INDEX PERSON_SURNAME_index ON PERSON(SURNAME);
这里是有问题的查询:
SELECT p.*
FROM PERSON p
WHERE p.NAME = 'name300' or p.SURNAME in (SELECT p2.SURNAME
FROM PERSON p2
WHERE p2.NAME = 'name500');
当我分析查询计划时,我发现它对人员 table 使用完全 table 访问权限。这大大减慢了我的查询时间,我不知道为什么会这样。
如果我消除第一个约束 (p.NAME = 'name300') 并仅使用 subselect 语句进行查询,则一切正常并且查询再次使用索引。
有人可以解释一下为什么查询没有在第一种情况下使用我的索引吗?
OR
数据库很难优化。您可以将其拆分为两个查询并使用 UNION ALL
:
SELECT p.*
FROM PERSON p
WHERE p.NAME = 'name300'
UNION ALL
SELECT p.*
FROM PERSON p
WHERE p.NAME <> 'name300' AND
p.SURNAME IN (SELECT p2.SURNAME
FROM PERSON p2
WHERE p2.NAME = 'name500'
);
我有一个包含 'or' 语句和 'inner select' 语句的查询。当我检查查询计划时,它使用完全 table 访问权限,我不知道为什么会这样。
我创建了这个测试用例来说明我的问题:
CREATE TABLE PERSON (
ID NUMBER(18) NOT NULL,
NAME VARCHAR2(18) NOT NULL,
SURNAME VARCHAR2(18) NOT NULL
);
BEGIN
FOR b IN 1..500000
LOOP
INSERT INTO PERSON VALUES (b,'name' || to_char(b),'surname' || to_char(b));
END LOOP;
END;
CREATE INDEX PERSON_NAME_index ON PERSON(NAME);
CREATE INDEX PERSON_SURNAME_index ON PERSON(SURNAME);
这里是有问题的查询:
SELECT p.*
FROM PERSON p
WHERE p.NAME = 'name300' or p.SURNAME in (SELECT p2.SURNAME
FROM PERSON p2
WHERE p2.NAME = 'name500');
当我分析查询计划时,我发现它对人员 table 使用完全 table 访问权限。这大大减慢了我的查询时间,我不知道为什么会这样。
如果我消除第一个约束 (p.NAME = 'name300') 并仅使用 subselect 语句进行查询,则一切正常并且查询再次使用索引。
有人可以解释一下为什么查询没有在第一种情况下使用我的索引吗?
OR
数据库很难优化。您可以将其拆分为两个查询并使用 UNION ALL
:
SELECT p.*
FROM PERSON p
WHERE p.NAME = 'name300'
UNION ALL
SELECT p.*
FROM PERSON p
WHERE p.NAME <> 'name300' AND
p.SURNAME IN (SELECT p2.SURNAME
FROM PERSON p2
WHERE p2.NAME = 'name500'
);