Моя проблема (или, по крайней мере, сообщение об ошибке) очень похожа на обработчике запросов закончились внутренние ресурсы - очень длинный SQL-запрос .
Мой клиент работает с SQL-запросом выбора, содержащим предложение where с ровно 100 000 записей.
Запрос не выполняется с ошибкой 8632 и сообщением об ошибке
Внутренняя ошибка: достигнут лимит служб экспрессии. Пожалуйста, поищите потенциально сложные выражения в вашем запросе и постарайтесь упростить их.)
Я нахожу очень странным, что это сообщение об ошибке выдается точно в 100 000 записей, поэтому мне интересно, если это настраиваемое значение. Это так, и если да, как я могу увеличить это значение до более высокого?
На MSDN есть предложение переписать запрос, но я бы хотел этого избежать.
Между тем я обнаружил, что список записей, о которых я говорю, содержит натуральные числа, довольно многие из них кажутся последовательными (что-то вроде (1,2,3,6,7,8,9,10,12, 13,15,16,17,18,19,20).
Это делает выражение SQL where-что-то вроде:
where entry in (1,2,3,6,7,8,9,10,12,13,15,16,17,18,19,20)
Я мог бы преобразовать это в:
where (entry between 1 and 3) OR
(entry between 6 and 10) OR
(entry between 12 and 13) OR
(entry between 15 and 20)
Можно ли это сократить на:
where entry in (1,...,3,6,...,10,12,13,15,...,20)
... или что-то подобное? (Я знаю, что это длинный путь, но это сделает обновления программного обеспечения более легкими и удобочитаемыми)
К вашему сведению: данные в предложении where являются результатом вычислений, выполненных в другой таблице: сначала записи этой таблицы читаются и фильтруются в начале, затем выполняется некоторая дополнительная обработка (что невозможно сделать с помощью SQL), результатом этой дополнительной обработки является дополнительная фильтрация, результат которой используется в предложении where. Поскольку было невозможно написать полную фильтрацию в SQL, упомянутый метод был использован. Очевидно, что содержимое предложения where может меняться при каждой обработке, поэтому необходимо динамическое решение.
источник
WHERE IN
не поддерживает такой синтаксис диапазона. Кроме того , она должна бытьWHERE () OR () OR ()
не AND. Но чтобы воспользоваться предложением Брента, вам не нужно менять весь запрос, вы можете просто сделать этоWHERE IN (SELECT myID FROM #biglist)
. И это#biglist
может быть либо реальная (постоянная) таблица, либо временная таблица, которую вы создаете на лету.Ответы:
Чтобы найти более 100 000 значений, поместите их во временную таблицу, по одной строке на каждое искомое значение. Затем присоедините ваш запрос к этой временной таблице для фильтрации.
Что-то с более чем 100 000 значений не является параметром - это таблица. Вместо того, чтобы думать о повышении лимита, рассмотрите правило десяти процентов Swart : если вы приближаетесь к 10% лимита SQL Server, у вас, вероятно, будет плохое время.
источник
Если вы все равно хотите изменить приложение, подумайте
(a) используя TVP для всего набора значений - вы должны создать
DataTable
в C # и передать его в хранимую процедуру, используяStructuredType
, как я продемонстрирую здесь . (Надеюсь, 100 000 записей - это ненормально, поскольку масштабируемость может быть проблемой независимо от того, какой подход вы используете.)или
(б) использование TVP для передачи верхних и нижних границ диапазонов и написание немного другого соединения (спасибо @ypercube).
источник
Нет, это не настраивается, и вы не можете увеличить его до более высокого.
В упомянутой статье MSDN и других статьях предлагается обходной путь. Я упомянул два здесь, но вы можете искать больше.
источник
Просто мои 2 ¢ относительно сокращения условия запроса: -
Если вы можете
entry
заранее определить все возможные значения , будет ли это возможным, если вы примете дополнение к своему запросу?Перед
После
источник
Трудно понять, что вы пытаетесь выполнить, не имея возможности увидеть запрос, но здесь мы идем, предполагая, что вашему запросу нужны только две таблицы, одна с данными, другая со значениями, которых вы хотите избежать:
where entry in (<list of 100.000 values>)
ужасно ужасно, как с точки зрения эффективности, так и с точки зрения обслуживания.where entry in (select whatever from table)
это так же ужасно, как и раньше. Тем не менее, в зависимости от особенностей таблиц и механизма SQL, он может работать нормально, несмотря на рак роговицы. (Может быть, хорошо в Oracle, никогда не будет в MySQL, не могу вспомнить о MSSQL).По моему мнению (не зная запроса вообще), вы должны переписать запрос следующим образом:
Если эти 100 000 значений всегда одинаковы, не полагаясь на остальную часть запроса, вы должны загрузить эти значения в таблицу (table_fixed_values) и использовать
Если эти 100 000 значений не совпадают, должна быть какая-то логика для подбора этих 100 000 значений, логика, которую вы должны встроить в
ON
предыдущий запрос.источник
LEFT JOIN table_fixed_values ON A.entry=B.entry WHERE B.entry IS NOT NULL
а не эквивалент, проще и проще для чтенияINNER JOIN table_fixed_values ON A.entry=B.entry
?