#sql #oracle #join #inner-join
#sql #Oracle #Присоединиться #внутреннее соединение
Вопрос:
В приведенном ниже запросе есть 3 таблицы, в которых мне нужно выполнить 2 соединения, чтобы получить информацию о столбце, это очень медленно, есть ли какой-нибудь эффективный способ выполнить этот запрос?
SELECT DISTINCT
st.status_c1
FROM
schemaname.tablea st
INNER JOIN (
SELECT
lic.SpecId AS applicationid,
lic.comData AS combusappid,
lic.ageId,
lic.licId,
lic.licid,
lic.appid,
com.nybe_bustbl_id AS busid
FROM
schemaname.tableb lic
INNER JOIN tablec com ON lic.comData = com.comData
WHERE
lic.ageId = '12'
) rt ON
st.ageId = rt.ageId
AND
st.licId = rt.licId
AND
st.licid = rt.licid
AND
st.appid = rt.appid
WHERE
status_id = 3;
Комментарии:
1. При любой проблеме с производительностью вам следует подумать о том, как бы вы ее выполнили, с какой таблицы вы начнете? Как вы получите доступ к таблице с ее фильтрами? Тогда к какому столу вы присоединитесь? Будете ли вы выполнять поиск для каждой строки из вашего первого запроса или это приведет к выполнению такого количества небольших поисковых запросов, что вы с таким же успехом можете читать из следующей таблицы, используя другие ее фильтры. Теперь, когда вы подумали об этом, проверьте, что думает Oracle, просмотрев план выполнения, а также получите статистику выполнения источника строк, чтобы увидеть, куда пошла вся работа.
Ответ №1:
Ваш текущий запрос создаст дополнительные строки при выполнении JOIN
условия для нескольких записей в любой таблице, а затем DISTINCT
отфильтрует эти дубликаты. Вы можете попытаться сократить объем работы по фильтрации дубликатов, используя EXISTS
:
SELECT DISTINCT
st.status_c1
FROM schemaname.tablea st
WHERE status_id = 3
AND EXISTS (
SELECT 1
FROM schemaname.tableb lic
WHERE lic.ageId = '12'
AND st.ageId = lic.ageId
AND st.licId = lic.licId
AND st.appid = lic.appid
AND EXISTS(
SELECT 1 FROM tablec com WHERE lic.comData = com.comData
)
);
Ответ №2:
В запросе есть куча избыточности (licid находится в SELECT и ON дважды), и вам не нужно использовать подзапросы для этого. Я думаю, это сработает:
SELECT DISTINCT st.status_c1
FROM tablea st
INNER JOIN tableb lic ON st.ageId = lic.ageId
AND st.licId = lic.licId
AND st.appid = lic.appid
INNER JOIN tablec com ON lic.comData = com.comData
WHERE status_id = 3
and lic.ageId = '12'
Комментарии:
1. Большое вам спасибо за обновление, но когда я проверяю стоимость, я не вижу никаких изменений в стоимости, и выполняется полное сканирование таблицы для каждой таблицы, есть ли способ снизить стоимость?
Ответ №3:
Как часто вы собираетесь запускать этот запрос, сколько времени это занимает сейчас и каково объяснение. Выполняются ли statistcs для всех таблиц tha. Есть много вещей, о которых мы можем подумать, но для начала, если возможно, не могли бы вы, пожалуйста, дать нам подобную структуру таблицы и объяснить план запроса. Также может быть указатель на таблицу status_c1 tablea help. Как указывалось, попробуйте удалить условие соединения, которое выполняется дважды, И st.licid = rt.licid
SELECT DISTINCT st.status_c1
FROM schemaname.tablea st
INNER JOIN (
SELECT
lic.SpecId AS applicationid, lic.comData AS combusappid, lic.ageId, lic.licId, lic.licid,
lic.appid, com.nybe_bustbl_id AS busid
FROM schemaname.tableb lic
INNER JOIN tablec com ON lic.comData = com.comData
WHERE lic.ageId = '12'
) rt ON st.ageId = rt.ageId AND st.licId = rt.licId AND st.licid = rt.licid AND st.appid = rt.appid
WHERE status_id = 3;