Сокращение вложенных циклов при поиске в нескольких столбцах нескольких значений - PullRequest
0 голосов
/ 05 июня 2019

Я пытаюсь определить, может ли такая функция, как EXISTS или COALESCE, уменьшить интенсивное использование вложенных циклов при поиске любого совпадения по 300 значениям, которые могут встречаться в 16 различных столбцах.

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

SELECT
 A.product_id

FROM
  A inner join B on A.id = B.id
    inner join C on A.id = C.id

WHERE
   B.code1 in ('x1','x2','x3', ... 'x298', 'x299', 'x300')
or B.code2 in ('x1','x2','x3', ... 'x298', 'x299', 'x300')
or C.code3 in ('x1','x2','x3', ... 'x298', 'x299', 'x300')
 ...
or C.code15 in ('x1','x2','x3', ... 'x298', 'x299', 'x300')
or C.code16 in ('x1','x2','x3', ... 'x298', 'x299', 'x300')

Хотя поставляемый код работает, его стоимость высока, и я был бы признателен за помощь в улучшении времени выполнения.

Ответы [ 2 ]

1 голос
/ 05 июня 2019

Одним простым улучшением было бы разделение этого на два запроса:

SELECT A.product_id
FROM A JOIN
     B 
     ON A.id = B.id
WHERE B.code1 in ('x1','x2','x3', ... 'x298', 'x299', 'x300') OR
      B.code2 in ('x1','x2','x3', ... 'x298', 'x299', 'x300')
UNION ALL   -- or UNION to remove duplicates
SELECT A.product_id
FROM A JOIN
     C 
     ON A.id = C.id
WHERE C.code3 in ('x1','x2','x3', ... 'x298', 'x299', 'x300') OR
      ...
      C.code15 in ('x1','x2','x3', ... 'x298', 'x299', 'x300') OR
      C.code16 in ('x1','x2','x3', ... 'x298', 'x299', 'x300');

Как я уже сказал в комментарии, лучшей моделью данных была бы таблица с одной строкой на id и code.

0 голосов
/ 05 июня 2019

Попробуйте присоединиться к списку кодов. Мне интересно, улучшит ли это вашу производительность или нет:

select A.product_id
from A
inner join B on B.id = A.id
inner join C on C.id = A.id
inner join (values ('x1'),('x2'),('x3'), ... ('x298'), ('x299'), ('x300')) as v(code)
    on v.code = B.code1 
    or v.code = B.code2
    or v.code = C.code3
    ...
    or v.code = C.code16

В качестве альтернативы, вы можете отключить таблицы B и C, чтобы все значения столбцов codeN были в одном столбце, а затем отфильтровать этот единственный столбец по вашим 300 значениям.

...