0

我有一个带有“或”语句和“内部选择”语句的查询。当我检查查询计划时,它使用全表访问,我不知道为什么会发生这种情况。

我创建了这个测试用例来显示我的问题:

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');

当我分析查询计划时,我看到它对人员表使用全表访问。这大大减慢了我的查询时间,我不知道为什么会这样。

如果我消除第一个约束(p.NAME = 'name300')并仅使用 subselect 语句进行查询,则一切正常,查询再次使用索引。

有人可以解释一下为什么查询没有在第一种情况下使用我的索引吗?

4

1 回答 1

1

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'
                   );
于 2019-01-02T11:52:53.020 回答