Table Valued Constructor Максимальное ограничение строк в Select

У меня есть Table Valued Constructor, через который я выбираю около 1 million записей. Он будет использоваться для update другой таблицы.

SELECT *
FROM   (VALUES (100,200,300),
               (100,200,300),
               (100,200,300),
               (100,200,300),
               .....
               ..... --1 million records
               (100,200,300)) tc (proj_d, period_sid, val) 

Вот мой исходный запрос: https://www.dropbox.com/s/ezomt80hsh36gws/TVC.txt?dl=0#

Когда я делаю вышеуказанное select, он просто показывает Запрос выполнен с ошибками с отображением любого сообщения об ошибке.

введите здесь описание изображения

Обновление: Попытка поймать сообщение об ошибке или номер ошибки с помощью блока TRY/CATCH, но не использовать ту же ошибку, что и на предыдущем изображении.

BEGIN try
    SELECT *
    FROM   (VALUES (100,200,300),
                    (100,200,300),
                    (100,200,300),
                    (100,200,300),
                    .....
                    ..... --1 million records
                    (100,200,300)) tc (proj_d, period_sid, val) 
END try

BEGIN catch
    SELECT Error_number(),
           Error_message()
END catch 

Почему он не выполняется, есть ли ограничения для конструктора таблицы Valed в Select. Я знаю, что для Insert это 1000, но я выбираю здесь.


person Pரதீப்    schedule 07.11.2016    source источник
comment
проверьте эту ссылку: заголовок stackoverflow.com/questions/14790548/   -  person Laxmi    schedule 07.11.2016
comment
Все литеральные значения должны быть скомпилированы в план выполнения. Сколько времени требуется для компиляции, прежде чем вы увидите ошибку?   -  person Martin Smith    schedule 07.11.2016
comment
@MartinSmith - всегда менее 5 секунд   -  person Pரதீப்    schedule 07.11.2016
comment
Я пробовал это, и через восемь минут он все еще борется без результатов или ошибок (пока) DECLARE @SQL NVARCHAR(MAX) = '(100,200,300),' ; SELECT @SQL = 'SELECT * FROM (VALUES ' + REPLICATE(@SQL,1000000) + '(100,200,300)) tc (proj_d, period_sid, val)';EXEC(@SQL)   -  person Martin Smith    schedule 07.11.2016
comment
@MartinSmith - Он конкурировал?   -  person Pரதீப்    schedule 07.11.2016
comment
Я дал ему поработать в течение 28 минут, а затем выключил его. Вероятно, он делал что-то вроде этого операторы вставки против одиночной вставки с несколькими значениями"> stackoverflow.com/questions/8635818/   -  person Martin Smith    schedule 07.11.2016
comment
TRY/CATCH не перехватывает ошибки с серьезностью 10 или ниже. Попробуйте получить номер ошибки/сообщение сразу после SELECT.   -  person TT.    schedule 07.11.2016
comment
@TT.- Попробовал, результат NULL для обеих функций:/   -  person Pரதீப்    schedule 07.11.2016
comment
Было бы интересно увидеть предполагаемые и фактические (если возможно) планы запросов. Используйте pastebin.com или что-то подобное, чтобы опубликовать план в формате XML. Также можно попытаться найти переломный момент, количество значений, после которого запрос обрывается.   -  person Vladimir Baranov    schedule 07.11.2016
comment
@VladimirBaranov - к сожалению, план выполнения также не создается. Опубликую свой оригинальный код на 1 миллион   -  person Pரதீப்    schedule 07.11.2016
comment
@VladimirBaranov - обновил вопрос оригинальным запросом   -  person Pரதீப்    schedule 07.11.2016
comment
@MartinSmith - обновил вопрос оригинальным запросом   -  person Pரதீப்    schedule 07.11.2016
comment
Скорее всего движку не хватает памяти при составлении плана. Память для планов и для компиляции отделена от буферного пула для данных, насколько я понимаю. На самом деле он никогда не пытается выполнить запрос. До этого этапа не доходит. Вот почему TRY ... CATCH ничего не поймать. Попробуйте выполнить меньший запрос (10 000–20 000 строк) и найдите CompileMemory и CachedPlanSize в XML фактического плана. Вы получите представление о том, сколько памяти потребуется для 1 млн строк.   -  person Vladimir Baranov    schedule 07.11.2016
comment
Запустив его непосредственно в SSMS, он, безусловно, выйдет из строя намного быстрее. Через 3-5 секунд так что-то отличается от EXEC дела.   -  person Martin Smith    schedule 07.11.2016
comment
Пробовали ли вы создать TRACE в SQL Server Profiler для ошибок и предупреждений, чтобы увидеть, дает ли это какое-либо указание на ошибку, о которой сообщается в SSMS?   -  person TT.    schedule 07.11.2016


Ответы (2)


Нет соответствующего жестко запрограммированного ограничения (65 536 * Размер сетевого пакета 4 КБ составляет 268 МБ, а длина вашего сценария и близко не соответствует этому), хотя не рекомендуется использовать этот метод для большого количества строк.

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

DECLARE @SQL NVARCHAR(MAX) = '(100,200,300),
';

SELECT @SQL = 'SELECT * FROM (VALUES ' + REPLICATE(@SQL, 1000000) + '
(100,200,300)) tc (proj_d, period_sid, val)';

SELECT @SQL AS [processing-instruction(x)]
FOR XML PATH('')

SELECT DATALENGTH(@SQL) / 1048576.0 AS [Length in MB] --30.517705917

EXEC(@SQL);

Хотя я убил вышеприведенное после ~ 30 минут компиляции, и он все еще не создал строку. Буквенные значения должны храниться внутри самого плана в виде таблицы констант, и SQL Server тратит много времени, пытаясь также получить свойства о них.

SSMS — это 32-разрядное приложение, которое выдает исключение std::bad_alloc при анализе пакета.

введите здесь описание изображения

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

Емкость вектора увеличивается на 50 % каждый раз (т. е. в соответствии с этой последовательностью). Емкость, до которой должен расти вектор, зависит от того, как устроен код.

Следующие должны вырасти с вместимости 19 до 28.

SELECT * FROM 
(VALUES 
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300),
(100,200,300)) tc (proj_d, period_sid, val)

и следующему нужен только размер 2

SELECT * FROM (VALUES (100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300)) tc (proj_d, period_sid, val)

Для следующего требуется емкость > 63 и ‹= 94.

SELECT *
FROM   (VALUES 
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300),
      (100,
       200,
       300)
       ) tc (proj_d, period_sid, val) 

Для миллиона строк, расположенных, как в случае 1, емкость вектора должна вырасти до 3 543 306.

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

  1. Уменьшите количество разрывов строк.
  2. Перезапуск SSMS в надежде, что запрос на большой объем непрерывной памяти будет выполнен успешно при меньшей фрагментации адресного пространства.

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

Вам будет гораздо лучше использовать мастер импорта-экспорта для загрузки таблицы. Если вам нужно сделать это в TSQL, вы обнаружите, что разбиваете его на более мелкие пакеты и / или используете другой метод, такой как измельчение XML, который будет работать лучше, чем конструкторы с табличным значением. Например, следующее выполняется за 13 секунд на моей машине (хотя при использовании SSMS вам все равно, вероятно, придется разбиваться на несколько пакетов, а не вставлять массивный строковый литерал XML).

DECLARE @S NVARCHAR(MAX) = '<x proj_d="100" period_sid="200" val="300" />
' ; 

DECLARE @Xml XML = REPLICATE(@S,1000000);

SELECT 
    x.value('@proj_d','int'),
    x.value('@period_sid','int'),
    x.value('@val','int')
FROM @Xml.nodes('/x') c(x)
person Martin Smith    schedule 07.11.2016

Проверьте это для ограничений запросов: https://msdn.microsoft.com/en-us/library/ms143432.aspx

person Dexion    schedule 07.11.2016