ORACLE sql Явное предоставление значений в предложении WHERE, показывающее гораздо лучшую производительность по сравнению с использованием подзапроса - PullRequest
2 голосов
/ 12 марта 2019

Я новичок в оракуле

У меня есть 2 таблицы, чтобы присоединиться огромный_таблик содержит около 1 миллиарда строк big_table содержит около 100 миллионов строк и небольшие таблицы содержат 999 строк, обеспечивающих условие фильтрации

small_table.num_id для совпадения с огромным_table.num_id столбцом

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

В частности, если посмотреть на результат плана объяснения Этот запрос выполняется намного быстрее с количеством элементов 100 и стоимостью 6

.
SELECT h.col_required, b.col_required, h.num_id
FROM  huge_table h,
      big_table b
WHERE h.row_id = b.xx_id
  AND b.status = 'up'
  AND h.num_id in ('num1', 'num2',... 'num100')  -- Explicitly providing the values that in 
                                                 -- small_table`

Этот запрос с подзапросом намного медленнее с количеством элементов 1445704 и стоимостью 660293

SELECT h.col_required, b.col_required, h.num_id
FROM huge_table h, big_table b
WHERE h.row_id = b.xx_id
  AND b.status = 'up'
  AND h.num_id in ('SELECT num_id FROM small_table)  -- Using sub query 
                                                     -- provide the values

Я также пытался использовать WHERE выходы или INNER JOIN для small_table, оба обеспечивали похожий результат с подзапросом.

Вопрос, который у меня возникает, заключается в том, можно ли добиться хорошей производительности без явного указания значений в предложении where?

Спасибо

Я наконец выяснил причины, вызвавшие эту проблему.

В small_table типом данных для num_id является NVARCHAR2 (255) В огромной таблице типом данных для num_id является VARCHAR2 (255).

В основном, после того, как я преобразовал тип данных, время запроса сократилось.

Ответы [ 2 ]

0 голосов
/ 12 марта 2019

Вы можете попробовать с exists:

SELECT h.col_required, b.col_required, h.num_id
FROM huge_table h join
     big_table b
     on h.row_id = b.xx_id
WHERE b.status = 'up' AND
      EXISTS (SELECT 1
              FROM small_table st
              WHERE h.num_id = st.num_id
             );

В частности, для этого может быть использован индекс на small_table(num_id), а также любые другие индексы, которые есть у вас в других таблицах.

0 голосов
/ 12 марта 2019

Этот ответ является умозрительным, но одним из возможных объяснений производительности, которую вы видите, является то, что Oracle выполняет подзапрос в предложении WHERE несколько раз во втором запросе.То есть, вместо того, чтобы выполнять его один раз и кэшировать результирующий набор, работа выполняется несколько раз.Если вы переписываете запрос с использованием явного объединения, это может обойти эту проблему:

SELECT h.col_required, b.col_required, h.num_id
FROM huge_table h
INNER JOIN big_table b
    ON h.row_id = b.xx_id
INNER JOIN small_table s
    ON h.num_id = s.num_id
WHERE
    b.status = 'up';

Вы также можете добавить следующий индекс на num_id к small_table:

CREATE INDEX idx ON small_table (num_id);

Это может помочь Oracle быстрее выполнить второе соединение / поиск.

...