FOR XML
foi introduzido no SQL Server 2000. SQL Server 2000 não tinha
MAX
tipos de dados ou o XML
tipo de dados. Nem foi possível usar FOR XML
em uma subconsulta. O artigo O que o lado do servidor FOR XML retorna? explica
No SQL Server 2000 ...FOR XML
... foi implementado na camada de código entre o processador de consultas e a camada de transporte de dados ... o processador de consultas produz o resultado da mesma forma que semFOR XML
e entãoFOR XML
code formata o conjunto de linhas como XML. Para desempenho máximo de publicação XMLFOR XML
faz a formatação XML do conjunto de linhas resultante e envia diretamente sua saída para o código TDS do lado do servidor em pequenos pedaços sem buffer XML inteiro no espaço do servidor. O tamanho do bloco é de 2.033 caracteres UCS-2. Assim, XML com mais de 2033UCS-2 caracteres é enviado para o lado do cliente em várias linhas, cada uma contendo um pedaço do XML. O SQL Server usa um nome de coluna predefinido para este conjunto de linhas com uma coluna do tipoNTEXT
-“XML_F52E2B61-18A1-11d1-B105-00805F49916B
” – para indicar o XMLrowset em partes na codificação UTF-16.
Portanto, parece que isso ainda é implementado da mesma maneira para
FOR XML
de nível superior em versões posteriores também. O SQL Server 2005 introduziu a capacidade de usar
FOR XML
em subconsultas (o que significa que agora elas precisam ser tratadas pelo processador de consultas em vez de uma camada fora dele enquanto transmite os resultados para o cliente) O mesmo artigo explica que eles serão digitados como
NVARCHAR(MAX)
ou XML
dependente da presença ou não de um type
diretiva. Assim como a diferença de tipo de dados, isso significa o
SELECT
adicional wrapper pode fazer uma diferença drástica no desempenho se #tab
é grande. /*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
É possível ver as diferentes abordagens nas pilhas de chamadas, bem como os planos de execução.
Transmitido diretamente
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
Com subconsulta
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
Ambos acabam chamando o mesmo código XML subjacente, mas a versão "desempacotada" não possui iteradores XML no próprio plano, o resultado é alcançado substituindo as chamadas de método de
CXStmtSelect
com CXStmtXMLSelect
em vez disso (representado no plano como um nó raiz XML Select em vez de um Select simples e antigo). No SQL Server 2016 CTP3, ainda vejo
ntext
para FOR XML
de nível superior . No entanto, FOR JSON
de nível superior aparece como nvarchar(max)
Pelo menos no CTP, o nome da coluna especial JSON ainda contém o GUID
F52E2B61-18A1-11d1-B105-00805F49916B
apesar do fato de que a origem disso é a Interface IXMLDocument. Os planos parecem os mesmos, embora o XML Select seja substituído por um JSON Select
BTW:Na compilação
Microsoft SQL Server 2014 - 12.0.4213.0 (X64)
Não vejo nenhuma diferença de comportamento entre tabelas temporárias e tabelas permanentes. Isso provavelmente se deve a diferentes @@Version
entre os ambientes que sua pergunta usa http://sqlfiddle.com/ (12.0.2000.8) e https://data.stackexchange.com/ (12.0.4213.0). Talvez um bug tenha sido corrigido em
sys.dm_exec_describe_first_result_set
entre as duas versões de 2014. Em 2012 recebo os mesmos resultados que Shnugo em 11.0.5343.0 (com
NULL
nas três primeiras linhas), mas depois de instalar o SP3 11.0.6020.0 recebo o mesmo que seus resultados iniciais mostrados na pergunta.