План запроса SQL sql не использует индексы с оператором или и подзапрос
У меня есть запрос с оператором "или" и "внутренним выбором". Когда я проверяю план запроса, он использует полный доступ к таблице, и я не знаю, почему это происходит.
Я создал этот тестовый пример, чтобы показать мою проблему:
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 ответ
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'
);