Используя “В” в операторе Where, где количество объектов в наборе является очень большим

14
задан Karim 10 February 2009 в 12:55
поделиться

9 ответов

Я всегда использовал бы

WHERE id IN (1,2,3,4,.....10000)

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

редактирование: Например, направляющие делает это много негласно

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

9
ответ дан 1 December 2019 в 07:19
поделиться

Другая альтернатива должна сохранить те числа во временной таблице и использовать ее в соединении, чтобы сделать обновление. Если Вы можете выполниться, единственный оператор обновления определенно лучше, чем выполнение одного оператора на запись.

15
ответ дан 1 December 2019 в 07:19
поделиться

В Oracle существует предел значений, которые можно поместить в В пункте. Таким образом, Вы лучше используете a ИЛИ, x=1 или x=2... они не ограничены, насколько я знаю.

2
ответ дан 1 December 2019 в 07:19
поделиться

Как Вы генерируете В пункте?

, Если существует там другой оператор SELECT, который генерирует те значения, Вы могли просто включить это в ОБНОВЛЕНИЕ как так:

UPDATE TARGET_TABLE T
SET
  SOME_VALUE = 'Whatever'
WHERE T.ID_NUMBER IN(
                    SELECT ID_NUMBER  --this SELECT generates your ID #s.
                    FROM SOURCE_TABLE
                    WHERE SOME_CONDITIONS
                    )

В некотором RDBMses, Вы доберетесь, лучшая производительность при помощи СУЩЕСТВУЕТ синтаксис, который был бы похож на это:

UPDATE TARGET_TABLE T
SET
  SOME_VALUE = 'Whatever'
WHERE EXISTS (
             SELECT ID_NUMBER  --this SELECT generates your ID #s.
             FROM SOURCE_TABLE S
             WHERE SOME_CONDITIONS
               AND S.ID_NUMBER =  T.ID_NUMBER
             )
5
ответ дан 1 December 2019 в 07:19
поделиться

Я использовал бы табличную переменную / поддающийся соблазну; вставьте значения в это и соедините с ним. Затем можно использовать тот же набор многократно. Это работает особенно хорошо, если Вы (например), передаете CSV идентификаторов как varchar. Как пример SQL Server:

DECLARE @ids TABLE (id int NOT NULL)

INSERT @ids
SELECT value
FROM dbo.SplitCsv(@arg) // need to define separately

UPDATE t
SET    t. // etc
FROM   [TABLE] t
INNER JOIN @ids #i ON #i.id = t.id
2
ответ дан 1 December 2019 в 07:19
поделиться

Если бы Вы были на Oracle, то я рекомендовал бы использовать функции таблицы, подобные сообщению Marc Gravell.

-- first create a user-defined collection type, a table of numbers
create or replace type tbl_foo as table of number;

declare
  temp_foo tbl_foo;
begin
  -- this could be passed in as a parameter, for simplicity I am hardcoding it
  temp_foo := tbl_foo(7369, 7788);

  -- here I use a table function to treat my temp_foo variable as a table, 
  -- and I join it to the emp table as an alternative to a massive "IN" clause
  select e.*
    from emp e,
         table(temp_foo) foo
   where e.empno = foo.column_value;
end;
1
ответ дан 1 December 2019 в 07:19
поделиться

Не зная, каково "очень большое" количество идентификатора могло бы быть, я буду рисковать предположением. ;-)

, Так как Вы используете Доступ в качестве базы данных, количество идентификатора не может быть тот высоко. Принятие, о котором мы говорим меньше, чем, говорят 10 000 чисел, и мы должны знать, что ограничения контейнеров содержат идентификатор (какой язык используется для фронтэнда?), я придерживался бы одного UPDATE оператор; если это является самым читаемым и самым легким выполнить обслуживание на позже. Иначе я разделил их на несколько операторов с помощью некоторой умной логики. Чему-то нравится, разделяет оператор на несколько операторов с в один, десять, сотня, тысяча... Идентификатор на оператор.

Затем я предоставил бы оптимизатору DB право выполнять оператор (операторы), максимально эффективный. Я, вероятно, сделал бы 'объяснение' на запросе / запросы, чтобы удостовериться, что ничто глупое не продолжается все же.

, Но по моему опыту, нормально довольно часто оставлять этот вид оптимизации к самому менеджеру базы данных. Одной вещью, которая занимает большую часть времени, обычно является фактическое соединение к базе данных, поэтому если можно выполнить все запросы в рамках того же соединения, это обычно не проблемы. Удостоверьтесь, что Вы отсылаете весь UPDATE операторы, прежде чем Вы начнете изучать и ожидать любого возвращения наборов результатов все же. :-)

2
ответ дан 1 December 2019 в 07:19
поделиться

Я не знаю тип значений в Вашем В списке. Если они - большинство значений от 1 до 10 000, Вы смогли обрабатывать их для получения чего-то как:

WHERE MyID BETWEEN 1 AND 10000 AND MyID NOT IN (3,7,4656,987)

Или, если бы НЕ В списке все еще было бы длинно, обработав список и генерировав набор операторов BETWEEN:

WHERE MyID BETWEEN 1 AND 343 AND MyID BETWEEN 344 AND 400 ...

И т.д.

В последний раз всех, Вы не должны волноваться о том, как Струя обработает В пункте при использовании запроса к внешнему источнику данных. Вы не можете сделать этого в коде, но у Вас мог быть сохраненный QueryDef, который определяется как передача, и измените оператор Where в коде во времени выполнения для использования Вашего В списке. Затем это все выдано к SQL Server, и SQL Server решит лучше всего, как обработать его.

0
ответ дан 1 December 2019 в 07:19
поделиться

В целом существует несколько вещей рассмотреть.

  1. кэш парсинга оператора в DB. Каждый оператор, с различным количеством объектов в В пункте, должен быть проанализирован отдельно. Вы используете связанные переменные вместо литералов, правильно?
  2. Некоторые Базы данных имеют предел на количество объектов в В пункте. Для Oracle это 1000.
  3. При обновлении Вас блокируют записи. Если у Вас есть несколько отдельных операторов обновления, у Вас могут быть мертвые блокировки. Это означает, что необходимо быть осторожны относительно порядка, в котором Вы выпускаете свои обновления.
  4. задержка Туда и обратно к базе данных может быть высокой, даже для очень быстрого оператора. Это означает, что часто лучше управлять большим количеством записей сразу для сохранения разовый прохождением.

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

Используя временную таблицу может не улучшить производительность, потому что необходимо заполнить временную таблицу с идентификаторами. Экспериментирование и тесты производительности могут сказать Вам ответ здесь.

А, единственный В пункте, очень легко понять и поддержать. Это, вероятно, о чем необходимо волноваться сначала. Если Вы находите, что производительность запросов плоха, Вы могли бы хотеть попробовать другую стратегию и видеть, помогает ли она, но не оптимизируйте преждевременно. В ПУНКТЕ семантически корректен, так оставьте его в покое, если это не повреждается.

1
ответ дан 1 December 2019 в 07:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: