Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

ИЗБЕРЕТЕ ЗА XML AUTO и върнете типове данни

FOR XML беше въведен в SQL Server 2000.

SQL Server 2000 нямаше MAX типове данни или XML тип данни. Нито беше възможно да се използва FOR XML в подзаявка.

Статията Какво връща сървърната страна FOR XML? обяснява

В SQL Server 2000 ... FOR XML ... беше имплементиран в слоя код между процесора за заявки и транспортния слой на данни ... процесорът на заявки произвежда резултата по същия начин, както безFOR XML и след това FOR XML кодът форматира набора от редове като XML. За максимална производителност на XML публикуване FOR XML прави разпределящо XML форматиране на резултантния набор от редове и директно изпраща неговия изход към TDScode от страна на сървъра на малки парчета, без да буферира целия XML в сървърното пространство. Размерът на парчето е 2033 UCS-2 знака. По този начин XML, по-голям от 2033UCS-2 знака, се изпраща на страната на клиента в множество реда, всеки от които съдържа част от XML. SQL Server използва предварително дефинирано име на колона за този набор от редове с една колона от тип NTEXT -“XML_F52E2B61-18A1-11d1-B105-00805F49916B ” – за указване на XMLrowset на парчета в UTF-16 кодиране.

Така че изглежда, че това все още се изпълнява по същия начин за най-високо ниво FOR XML и в по-късни версии.

SQL Server 2005 въведе възможността за използване на FOR XML в подзаявки (което означава, че те сега трябва да се обработват от процесора на заявки, а не от слой извън него, докато се предават резултатите към клиента)

Същата статия обяснява, че те ще бъдат въведени като NVARCHAR(MAX) или XML в зависимост от наличието или не на type директива.

Освен разликата в типа данни, това означава допълнителния SELECT wrapper може да направи драстична разлика в производителността, ако #tab е голям.

/*Can be streamed straight out to client without using server storage*/
SELECT col
FROM #tab
FOR XML AUTO

/*XML constructed in its entirety in tempdb first*/
SELECT(SELECT col
FROM #tab
FOR XML AUTO) AS wrapped_subquery

Възможно е да видите различните подходи в стековете на обажданията, както и плановете за изпълнение.

Директно поточно

sqllang.dll!CXMLExecContext::AddTagAndAttributes()  + 0x5a9 bytes                   
sqllang.dll!CXMLExecContext::AddXMLRow()  + 0x2b7 bytes                 
sqltses.dll!CEsExec::FastMoveEval()  + 0x9c bytes                   
sqllang.dll!CXStmtQuery::ErsqExecuteQuery()  + 0x280 bytes                  
sqllang.dll!CXStmtXMLSelect::WrapExecute()  + 0x2d7 bytes                   
sqllang.dll!CXStmtXMLSelect::XretDoExecute()  + 0x355 bytes                 
sqllang.dll!CXStmtXMLSelect::XretExecute()  + 0x46 bytes                    
sqllang.dll!CMsqlExecContext::ExecuteStmts<1,1>()  + 0x368 bytes                    
sqllang.dll!CMsqlExecContext::FExecute()  + 0x6cb bytes                 
sqllang.dll!CSQLSource::Execute()  + 0x3ee bytes                    
sqllang.dll!process_request()  + 0x757 bytes    

С подзаявка

sqllang.dll!CXMLExecContext::AddTagAndAttributes()  + 0x5a9 bytes
sqllang.dll!CXMLExecContext::AddXMLRow()  + 0x2b7 bytes
sqllang.dll!CForXmlSerialize::ProcessRow()  + 0x19 bytes
sqllang.dll!CUDXR_Base::PushRow()  + 0x30 bytes
sqlmin.dll!CQScanUdx::Open()  + 0xd5 bytes
sqlmin.dll!CQueryScan::StartupQuery()  + 0x170 bytes
sqllang.dll!CXStmtQuery::SetupQueryScanAndExpression()  + 0x391 bytes
sqllang.dll!CXStmtQuery::InitForExecute()  + 0x34 bytes
sqllang.dll!CXStmtQuery::ErsqExecuteQuery()  + 0x217 bytes
sqllang.dll!CXStmtSelect::XretExecute()  + 0xed bytes
sqllang.dll!CMsqlExecContext::ExecuteStmts<1,1>()  + 0x368 bytes
sqllang.dll!CMsqlExecContext::FExecute()  + 0x6cb bytes
sqllang.dll!CSQLSource::Execute()  + 0x3ee bytes
sqllang.dll!process_request()  + 0x757 bytes

И двете в крайна сметка извикват един и същ основен XML код, но "разгърнатата" версия няма никакви XML итератори в самия план, резултатът се постига чрез замяна на извиквания на метод от CXStmtSelect с CXStmtXMLSelect вместо това (представен в плана като главен възел на XML Select, а не като обикновен стар Select).

На SQL Server 2016 CTP3 все още виждам ntext за най-високо ниво FOR XML . Въпреки това най-високо ниво FOR JSON се показва като nvarchar(max)

Поне в CTP името на специалната колона в JSON все още съдържа GUID F52E2B61-18A1-11d1-B105-00805F49916B въпреки факта, че произходът на това е IXMLDocument Interface.

Плановете изглеждат почти еднакви, въпреки че XML Select е заменен с JSON Select

BTW:При компилация Microsoft SQL Server 2014 - 12.0.4213.0 (X64) Не виждам никаква разлика в поведението между временните таблици и постоянните таблици. Това вероятно се дължи на различния @@Version между средите, които вашият въпрос използва http://sqlfiddle.com/ (12.0.2000.8) и https://data.stackexchange.com/ (12.0.4213.0).

Може би е отстранена грешка в sys.dm_exec_describe_first_result_set между двете версии от 2014 г.

През 2012 г. получавам същите резултати като Shnugo на 11.0.5343.0 (с NULL в първите три реда), но след инсталирането на SP3 11.0.6020.0 получавам същото като първоначалните ви резултати, показани във въпроса.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Код за валидиране на SQL скриптове

  2. Microsoft Access срещу SQL Server

  3. Грешка 40 на доставчика с име pipes не можа да отвори връзка към грешка 2 на SQL Server

  4. Неправилен синтаксис близо до ключовата дума 'with'...предишният израз трябва да бъде завършен с точка и запетая

  5. Разделени със запетая резултати в SQL