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

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

- SQL Server 2000

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

- SQL Server 2005

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

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

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


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

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

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

Ответов (8)

Решение

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

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

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

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

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

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

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

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

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

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

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

Разместите запрос: D

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

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

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

@Kevin, люблю эту футболку - говорит само за себя :-).

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

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