Максимальный размер для SQL Server Query? IN? Есть ли лучший подход?

Возможный дубликат:
T-SQL WHERE col IN (…)

Каков максимальный размер запроса SQL Server? (# символов)

Максимальный размер для предложения IN? Я думаю, что я видел что-то о том, что Oracle имеет ограничение на 1000 единиц, но вы можете обойти это вместе с ANDing 2 INs. Аналогичная проблема в SQL Server?

UPDATE Итак, какой был бы наилучший подход, если мне нужно будет сказать 1000 GUID из другой системы (Non Relational Database) и сделать "JOIN in code" в отношении SQL Server? Представляет ли он список 1000 GUID для предложения IN? Или есть другой метод, который работает более эффективно?

Я не тестировал это, но мне интересно, могу ли я представить GUID как XML-документ. Например

<guids>
    <guid>809674df-1c22-46eb-bf9a-33dc78beb44a</guid>
    <guid>257f537f-9c6b-4f14-a90c-ee613b4287f3</guid>
</guids>

а затем выполните какой-то XQuery JOIN против Doc и таблицы. Менее эффективен, чем 1000 item IN.

Ответ 1

Каждая партия SQL должна соответствовать Ограничение размера партии: 65,536 * Размер сетевого пакета.

Кроме этого, ваш запрос ограничен условиями выполнения. Обычно он заканчивается размером стека, потому что x IN (a, b, c) не что иное, как x = a OR x = b OR x = c, который создает дерево выражений, подобное x = a OR (x = b OR (x = c)), поэтому он становится очень глубоким с большим количеством OR. SQL 7 ударил SO примерно в 10 тыс. Значений в IN, но теперь стеки намного глубже (из-за x64), поэтому он может пойти довольно глубокий.

Обновление

Вы уже нашли статью Erland на тему передачи списков/массивов SQL Server. С SQL 2008 вы также имеете Табличные параметры, которые позволяют передавать весь DataTable как один параметр типа таблицы и присоединяться к нему.

XML и XPath - еще одно жизнеспособное решение:

SELECT ...
FROM Table
JOIN (
   SELECT x.value(N'.',N'uniqueidentifier') as guid
   FROM @values.nodes(N'/guids/guid') t(x)) as guids
 ON Table.guid = guids.guid;

Ответ 2

Максимальные значения SQL Server раскрываются http://msdn.microsoft.com/en-us/library/ms143432.aspx (это версия 2008 года)

SQL Query может быть varchar (max), но отображается как ограниченный размером 65536 * Network Packet, но даже тогда наиболее вероятным для вас является 2100 параметров для каждого запроса. Если SQL захочет параметризовать литеральные значения в предложении in, я бы подумал, что вы нажмете этот предел сначала, но я его не тестировал.

Изменить: протестировать его, даже при принудительной параметризации, он выжил - я опробовал быстрый тест и выполнил его с 30 тыс. элементов в разделе "В". (SQL Server 2005)

В пунктах 100 тыс. потребовалось некоторое время, а затем сброшено с помощью:

Msg 8623, уровень 16, состояние 1, строка 1 Обработчик запросов исчерпал внутренние ресурсы и не смог создать план запроса. Это редкое событие и ожидается только для чрезвычайно сложных запросов или запросов, которые ссылаются на очень большое количество таблиц или разделов. Пожалуйста, упростите запрос. Если вы считаете, что получили это сообщение по ошибке, обратитесь в Службу поддержки клиентов за дополнительной информацией.

Таким образом, возможно 30k, но только потому, что вы можете это сделать - не означает, что вы должны:)

Изменить: Продолжается из-за дополнительного вопроса.

50k сработало, но вышло 60 тысяч, поэтому где-то там на моей тестовой установке btw.

Что касается того, как сделать это объединение значений без использования большого предложения, лично я создам временную таблицу, вставляю значения в эту временную таблицу, индексирую ее, а затем использую в соединении, предоставляя ей лучшие возможности для оптимизации объединений. (Генерация индекса в таблице temp создаст для него статистику, что поможет оптимизатору в качестве общего правила, хотя 1000 GUID не будут точно находить статистику слишком полезной.)

Ответ 3

За пакет, 65536 * Размер сетевого пакета, который составляет 4k, поэтому 256 МБ

Однако IN остановится раньше, но не будет точным.

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

Изменить: Remus напомнил мне: ошибка касается размера стека

Ответ 4

Можете ли вы загрузить идентификаторы GUID в таблицу царапин, затем выполните

... WHERE var IN SELECT guid FROM #scratchtable