Оптимизация запросов: использование (объединение вместо ИЛИ) и (существует вместо нуля) - PullRequest
0 голосов
/ 30 апреля 2019

У меня есть проблема оптимизации запросов.

для контекста, этот запрос всегда выполнялся мгновенно

, но сегодня это заняло гораздо больше времени.(3h +)

, поэтому я попытался это исправить.

Запрос похож на ->

Select someCols from  A 
 inner join B left join C   
Where A.date = Today 
And (A.col In ( Select Z.colseekedinA from tab Z)    --A.col is the same column for 
                                          -- than below
       OR
     A.col In ( Select X.colseekedinA from tab X)   

     )


    --    PART 1 ---
  Select someCols from  A 
  inner join B left join C    -- takes 1 second 150 lines
  Where A.date = Today 

   -- Part 2 ---
  Select Z.colseekedinA from tab Z
  OR  -- Union                         -- takes 1 seconds 180 lines
 Select X.colseekedinA from tab X

Когда я соединяю две части с помощью In,запрос становится невероятно длинным.

, поэтому я оптимизировал его с помощью объединения или OR и существует вместо in, но это все равно занимает 3 минуты

Я хочу сделать это снова до 5 секунд.

вы видите проблему с вопросом?

спасибо

Ответы [ 3 ]

1 голос
/ 30 апреля 2019

Использование Union и Exists

Select someCols 
from  A 
inner join B on a.col = b.col
left join C  on b.col = c.col
Where A.date = Today 
and exists(
 Select Z.colseekedinA from tab Z where Z.colseekedinA = A.col
 Union                        
 Select X.colseekedinA from tab X where x.colseekedinA = A.col )

Также, если возможно, измените ниже присоединение к Left присоединению.

inner join B on a.col = b.col 
1 голос
/ 30 апреля 2019

Существующий подход может дать ложные результаты, так как вы получите строки, которые не соответствуют ни одному из условий, только если 1 строка соответствует.Этого можно избежать, если использовать существующий в коррелированном подзапросе, но я не достаточно экспериментировал с этим, чтобы рекомендовать.

Для скорости я бы пошел на перекрестное применение и указал бы родительскую таблицу в перекрестном применении.выражение (коррелированный подзапрос для создания производной таблицы).Таким образом, условие соединения указывается перед возвратом данных, если у рассматриваемых столбцов есть индексы (т.е. они являются первичными ключами), то оптимизатор может разработать эффективный план для этого.

Объединение всехиспользуется в выражении перекрестного применения, поскольку это предотвращает четкую сортировку в производной таблице, которая, как правило, более тяжелая с точки зрения стоимости, чем возврат самих данных (объединение должно идентифицировать все строки в любом случае, включая дубликаты).

Наконец, еслиэто все еще медленно, тогда, возможно, вы захотите добавить индекс к столбцу даты в таблице a.Это преодолевает недостаток гибкости, свойственный столбцу даты, и означает, что оптимизатор может использовать индекс, а не сканировать все строки в наборе результатов и проверять, совпадает ли дата с сегодняшним днем.

Select someCols from  A 
 inner join B left join C   
 cross apply (Select Z.colseekedinA from tab Z where a.col=z.colseekedinA
              union all
              Select X.colseekedinA from tab X where a.col=x.colseekedina) d
Where A.date = Today 
0 голосов
/ 30 апреля 2019

Ваш код сбит с толку, но для первой части

Вы можете попробовать использовать select UNION для внутреннего подзапроса (с OR) и избежать предложения IN, используя внутренний JOIN

    Select someCols from  A 
    inner join B 
    left join C   
    INNER JOIN (
        Select Z.colseekedinA from tab Z
        UNION                                   
        Select X.colseekedinA from tab X
    ) t  on A.col = t.colseekedinA 
    Where A.date = Today 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...