Страница 1 из 1
Производительность запроса SELECT
Добавлено: 03 май 2008, 12:10
Ingwar
Как можно ускорить выполнение запроса:
Код: Выделить всё
SELECT ID FROM TOVARY WHERE NOT ID IN
(SELECT T_ID FROM STORAGE UNION
SELECT T_ID FROM INDETAILS UNION
SELECT T_ID FROM OUTDETAILS)
Индексы по полям T_ID в таблицах STORAGE, INDETAILS, OUTDETAILS существуют.
Добавлено: 03 май 2008, 17:16
Esperito
Попробуй использовать EXISTS вместо IN.
Добавлено: 04 май 2008, 09:34
Ingwar
Вопрос решен так:
Код: Выделить всё
SELECT T.ID, T.NAME, US.T_ID
FROM TOVARY T
LEFT OUTER JOIN (SELECT T_ID FROM STORAGE UNION
SELECT T_ID FROM INDETAILS UNION
SELECT T_ID FROM OUTDETAILS) US
ON US.T_ID=T.ID
WHERE US.T_ID IS NULL
Производительность почти в 500 раз выше (120 мс вместо 1 мин на существующей БД).
Источник:
http://www.az-design.ru/Support/DataBas ... 0002.shtml
Добавлено: 04 май 2008, 12:49
WildSery
А вот и плохо вопрос решён.
Правильно писать так:
Код: Выделить всё
SELECT T.ID, T.NAME, US.T_ID
FROM TOVARY T
WHERE NOT EXISTS
(
SELECT T_ID FROM STORAGE
UNION ALL
SELECT T_ID FROM INDETAILS
UNION ALL
SELECT T_ID FROM OUTDETAILS
)
Найди два отличия.
ЗЫ: А тому "источнику" надо идти букварь читать. Про оптимизацию NOT IN разными серверами, а также про NOT EXISTS, и как он реализован в различных серверах. Не написано даже, на каком сервере тест проводил. А ведь некоторые умеют даже данные не читать (индексное чтение), а ограничиваться _только_ чтением индекса.
Добавлено: 04 май 2008, 13:04
hvlad
WildSery писал(а):А вот и плохо вопрос решён.
Правильно писать так:
Код: Выделить всё
SELECT T.ID, T.NAME, US.T_ID
FROM TOVARY T
WHERE NOT EXISTS
(
SELECT T_ID FROM STORAGE
UNION ALL
SELECT T_ID FROM INDETAILS
UNION ALL
SELECT T_ID FROM OUTDETAILS
)
Найди два отличия.
WHERE кто писать будет ?
Добавлено: 04 май 2008, 13:34
Ingwar
WildSery писал(а):А вот и плохо вопрос решён.
Правильно писать так:
Код: Выделить всё
SELECT T.ID, T.NAME, US.T_ID
FROM TOVARY T
WHERE NOT EXISTS
(
SELECT T_ID FROM STORAGE
UNION ALL
SELECT T_ID FROM INDETAILS
UNION ALL
SELECT T_ID FROM OUTDETAILS
)
В приведенном тобой запросе используется US.T_ID, но в моем запросе US- обозначение комплексного UNION. У тебя же его нет, потому, я так понимаю, колонку US.T_ID нужно вообще удалить из запроса.
Тогда твой запрос у меня постоянно возвращает пустой набор, то есть не делает чего надо.
Добавлено: 04 май 2008, 13:53
WildSery
Влад верно сказал. Это я ещё кофе не попил.
Вот, поправил:
Код: Выделить всё
SELECT T.ID, T.NAME
FROM TOVARY T
WHERE NOT EXISTS
(
SELECT T_ID FROM STORAGE WHERE T_ID = T.ID
UNION ALL
SELECT T_ID FROM INDETAILS WHERE T_ID = T.ID
UNION ALL
SELECT T_ID FROM OUTDETAILS WHERE T_ID = T.ID
)
Добавлено: 04 май 2008, 15:11
Ingwar
WildSery писал(а):Влад верно сказал. Это я ещё кофе не попил.
Вот, поправил...
Да, спасибо, работает все супер. И приблизительно в 10 раз быстрее предложенного ранее мной варианта.
И еще: почему мой исходный запрос работает так ужасающе медленно? Где можно почитать об етом?
Добавлено: 04 май 2008, 15:21
Attid
Ingwar писал(а):
И еще: почему мой исходный запрос работает так ужасающе медленно?
условие where если мне не изменяет склероз выполняется на каждую запись чтоб определить есть там входящие записи, соответственно твой подзапрос выполняется пусть даже всего 1 секунду, будет выполняться столько раз сколько записей в товарах , и если их там хотябы 100 то выполнение всего запроса будет идти уже полторы минуты.
Добавлено: 04 май 2008, 16:11
WildSery
Ingwar писал(а):Где можно почитать об етом?
Думаю, лучше всего
статью Дмитрия Еманова о способах доступа.
Медленность в том, что рекурсивный перебор (читай в статье) усугублён дополнительно UNION.
План запроса скорее всего NATURAL для вложенных таблиц? Т.е. на каждый код из TOVARY выполняется объединение из трёх таблиц целиком!
Добавлено: 04 май 2008, 16:44
Ingwar
Спасибо всем кто откликнулся (и особенно WildSery)- проблема решилась

Добавлено: 29 май 2008, 11:42
Gera
Прошу прощения за столь поздний пост - раньше времени небыло
провел некоторое тестирование и по результатам запрос вида
Код: Выделить всё
SELECT T.ID, T.NAME
FROM TOVARY T
WHERE NOT EXISTS (SELECT T_ID FROM STORAGE WHERE T_ID = T.ID)
AND NOT EXISTS (SELECT T_ID FROM INDETAILS WHERE T_ID = T.ID)
AND NOT EXISTS (SELECT T_ID FROM OUTDETAILS WHERE T_ID = T.ID)
)
дал наименьшее время выполнения.
PS порядок таблиц также влияет на скорость. первой должна идти та, в которой наибольшая вероятность наличия записи
Добавлено: 29 май 2008, 12:37
WildSery
Gera писал(а):PS порядок таблиц также влияет на скорость. первой должна идти та, в которой наибольшая вероятность наличия записи
Порядок проверки предикатов, насколько я знаю, стохастический и зависит от конкретной структуры запроса.
Потому для каждого запроса надо уточнять, какой выполняется первым.