Вы когда-нибудь сталкивались с запросом, который SQL Server не смог выполнить из-за того, что он ссылался на слишком много таблиц?

StackOverflow https://stackoverflow.com/questions/2432

Вопрос

Вы когда-нибудь видели какие-либо из этих сообщений об ошибках?

-- SQL Server 2000

Не удалось выделить вспомогательную таблицу для разрешения вида или функции.
Было превышено максимальное количество таблиц в запросе (256).

-- SQL Server 2005

Слишком много имен таблиц в запросе.Максимально допустимое значение - 256.

Если да, то что вы сделали?

Сдался?Убедили заказчика упростить свои требования?Денормализовал базу данных?


@(все хотят, чтобы я опубликовал запрос):

  1. Я не уверен, смогу ли я вставить 70 килобайт кода в окно редактирования ответа.
  2. Даже если я смогу это сделать, это не поможет, поскольку эти 70 килобайт кода будут ссылаться на 20 или 30 просмотров, которые мне также пришлось бы опубликовать, поскольку в противном случае код будет бессмысленным.

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

Это было полезно?

Решение

Для SQL Server 2005 я бы рекомендовал использовать табличные переменные и частично создавать данные по ходу работы.

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

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

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

После завершения вы можете выполнить простой SELECT * из вашей табличной переменной и вернуть этот результирующий набор пользователю.

У меня нет никаких точных цифр для этого, но на сегодняшний день было три отдельных экземпляра, над которыми я работал, где выполнение этих небольших запросов на самом деле работало быстрее, чем выполнение одного массивного запроса select с кучей объединений.

Другие советы

Я никогда не сталкивался с подобной ситуацией, и, честно говоря, идея ссылаться на > 256 таблиц в запросе приводит меня в смертельный ужас.

Ваш первый вопрос, вероятно, должен быть "Почему так много?", за которым следует "какие фрагменты информации я знаю НЕТ нужно?" Я был бы обеспокоен тем, что объем данных, возвращаемых из такого запроса, также начнет довольно серьезно влиять на производительность приложения.

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

Это происходило бы постоянно при написании отчетов служб Reporting Services для установок Dynamics CRM, работающих на SQL Server 2000.CRM имеет хорошо нормализованную схему данных, которая приводит к большому количеству соединений.На самом деле есть исправление, которое увеличит лимит с 256 до колоссальных 260: http://support.microsoft.com/kb/818406 (мы всегда считали это отличной шуткой со стороны команды SQL Server).

Решение, как намекает Дилли-О, состоит в том, чтобы определить соответствующие "вложенные соединения" (предпочтительно те, которые используются несколько раз) и разложить их на переменные временной таблицы, которые вы затем используете в своих основных соединениях.Это серьезная PIA, которая часто снижает производительность.Мне жаль тебя.

@Кевин, обожаю эту футболку - этим все сказано :-).

Я хотел бы увидеть этот запрос, но я предполагаю, что это какая-то проблема с каким-то итератором, и хотя я не могу придумать ни одной ситуации, где это возможно, держу пари, что это из-за плохого while / case / cursor или тонны плохо реализованных представлений.

Отправьте запрос:D

Также я чувствую, что одной из возможных проблем может быть наличие тонны (читай 200+) таблиц имен / значений, которые можно было бы сконденсировать в единую таблицу подстановки.

У меня была такая же проблема...мое окно разработки запускает SQL Server 2008 (представление работало нормально), но на производстве (с SQL Server 2005) представление не работало.В итоге я создал представления, чтобы избежать этого ограничения, используя новые представления как часть запроса в представлении, которое выдало ошибку.

Немного глупо, учитывая, что логическое выполнение одно и то же...

Была такая же проблема в SQL Server 2005 (работала в 2008), когда я хотел создать представление.Я решил проблему, создав хранимую процедуру вместо представления.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top