План запроса SQL sql не использует индексы с оператором или и подзапрос - PullRequest
0 голосов
/ 02 января 2019

У меня есть запрос с оператором «или» и оператором «внутреннего выбора». Когда я проверяю план запроса, он использует полный доступ к таблице, и я не знаю, почему это происходит.

Я создал этот тестовый пример, чтобы показать мою проблему:

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, все работает нормально и запрос снова использует индексы.

Может кто-нибудь объяснить мне, почему запрос не использует мои индексы для первого случая?

1 Ответ

0 голосов
/ 02 января 2019

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'
                   );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...