【发布时间】:2019-01-02 11:48:31
【问题描述】:
我有一个带有“或”语句和“内部选择”语句的查询。当我检查查询计划时,它使用全表访问,我不知道为什么会发生这种情况。
我创建了这个测试用例来显示我的问题:
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');
当我分析查询计划时,我看到它对 person 表使用全表访问。这大大减慢了我的查询时间,我不知道为什么会这样。
如果我消除第一个约束(p.NAME = 'name300')并仅使用 subselect 语句进行查询,一切正常,查询再次使用索引。
有人能解释一下为什么第一种情况下查询没有使用我的索引吗?
【问题讨论】:
-
您是否收集了有关表格的统计信息?
-
经典问题。由于您的 OR,查询计划无法使用索引并陷入全表扫描。将您的 OR 更改为如下 Gordon 建议的 UNION。每当您编写 OR 时,您应该始终问自己是否可以用 UNION 替换它。
-
@BobJarvis 是的,我收集了统计数据。
标签: sql oracle indexing query-planner