2015-09-02 6 views
0

У меня есть внутреннее соединение, как так:INNER JOIN замедляя запрос

INNER JOIN Area AS area ON (Area.Id = psaLocalityOrCity.AreaId OR Area.Id = psaDbl.AreaId) 

psaLocalityOrCity являются места, которые мне нужны области для, однако есть некоторые записи, которые продублированы в psaLocalityOrCity. Эти и только эти, были извлечены в psaDbl как отдельные записи. INNER JOIN выше, предположим, чтобы найти все области для всех местностей в обеих группах, но этот оператор OR заставляет его работать веками. Для чего это было бы причиной? Есть ли какое-либо исправление, которое оптимизировало бы запрос на запуск за 6 секунд вместо 3мин?

+0

INNER JOIN с 'OR' не удивительно, что это медленно, См план выполнения и проверки использует индексы или выполнить полное сканирование таблицы – lad2025

+1

Показать все запросы, попробуйте 'WITH cte AS (SELECT * FROM psaLocalityOrCity UNION ALL SELECT * FROM psaDbl) SELECT * FROM tab JOIN cte', replace * с именами столбцов курса – lad2025

+0

проверьте, одинаковы ли типы этих идентификаторов. неявное литье является причиной 1-й медлительности в этих случаях. Причина № 2 - плохой или отсутствие индексов – jean

ответ

2

INNER JOIN с OR приведет к объединению вложенных циклов, наименьшему типу. Один из методов заключается в использовании UNION ALL, как это предлагается в комментарии. Другим является использование двух LEFT JOIN. Пример структуры:

SELECT . . ., 
     COALESCE(aloc.col1, adbl.col1) 
FROM psaLocalityOrCity loc LEFT JOIN 
    Area aloc 
    ON aloc.Id = loc.AreaId LEFT JOIN 
    Area adbl 
    ON adbl.Id = psaDbl.AreaId 
WHERE aloc.id is not null or adbl.id is not null 

Примечание: это не будет работать, если несколько строк в Area матче каждого столбца. Однако это кажется маловероятным, учитывая, что совпадение находится в столбце id.

-1

Есть какой-то способ повысить производительность этого типа запросов (но я не уверен, будет ли он работать для вас или нет.)

следующий может быть сделан для улучшения производительности:.

1. Использования WITH (NOLOCK) во всех таблицах
2. Если вы используете запрос много раз в день, попробуйте создать таблицу кэша, т.е. заполнить результат в таблице и использовать оператор select, чтобы всегда получать результат из таблицы.
3. Поместите только нужные столбцы в оператор select.

+0

с использованием ** nolock ** иногда рекомендуется, но может считаться плохой практикой, если используется слишком часто. В большинстве случаев это патч-решение по симптомам и скрывает реальную проблему. – jean

+0

Стоит сделать снимок. :) – Biswabid

0

Или присоединиться часто медленно
оптимизатора запросов входит в цикл присоединиться

JOIN Area AS area 
    ON Area.Id = psaLocalityOrCity.AreaId 
    OR Area.Id = psaDbl.AreaId 

не то же самое, как теперь у вас есть два AREA, чтобы иметь дело с
Но вы знаете, где площадь пришли
может привести к более строк, но будет быстрее
ответ от Linoff лучше

LEFT JOIN Area AS AreaCity 
    ON AreaCity.Id = psaLocalityOrCity.AreaId 
LEFT JOIN Area AS AreaDpl 
    ON AreaDpl.Id = psaDbl.AreaId 
-1

Извините, это удалось решить, объединив psaLocalityOrCity и psaDbl в один, используя SELECT с UNION. Это позволило мне исключить ИЛИ из INNER JOIN, и теперь запрос выполняется намного лучше. Есть идея отсюда: Is having an 'OR' in an INNER JOIN condition a bad idea?

Спасибо за все ваши предложения

Смежные вопросы