FOR XML
byl představen v SQL Server 2000.
SQL Server 2000 neměl MAX
datové typy nebo XML
datový typ. Nebylo také možné použít FOR XML
v dílčím dotazu.
Článek Co vrací server FOR XML? vysvětluje
V SQL Server 2000 ...
FOR XML
... byl implementován ve vrstvě kódu mezi dotazovacím procesorem a vrstvou přenosu dat ... dotazovací procesor vytváří výsledek stejným způsobem jako bezFOR XML
a potéFOR XML
kód formátuje sadu řádků jako XML. Pro maximální publikační výkonXMLFOR XML
provádí steaming XML formátování výsledné sady řádků a přímo posílá svůj výstup na server TDScode v malých kouscích bez ukládání celého XML do vyrovnávací paměti v prostoru serveru. Velikost chunku je 2033 UCS-2 znaků. XML větší než 2033UCS-2 znaků je tedy odesláno na stranu klienta ve více řádcích, z nichž každý obsahuje část XML. SQL Server používá pro tuto sadu řádků předdefinovaný název sloupce s jedním sloupcem typuNTEXT
-“XML_F52E2B61-18A1-11d1-B105-00805F49916B
” – pro označení blokové sady XMLrowset v kódování UTF-16.
Zdá se tedy, že toto je stále implementováno stejným způsobem pro nejvyšší úroveň FOR XML
i v pozdějších verzích.
SQL Server 2005 zavedl možnost používat FOR XML
v dílčích dotazech (což znamená, že tyto nyní musí být zpracovávány procesorem dotazů, nikoli vrstvou mimo něj při streamování výsledků klientovi)
Stejný článek vysvětluje, že budou zadány jako NVARCHAR(MAX)
nebo XML
závisí na přítomnosti či nepřítomnosti type
směrnice.
Stejně jako rozdíl mezi datovými typy to znamená další SELECT
wrapper může způsobit drastický rozdíl ve výkonu, pokud #tab
je velký.
/*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
Je možné vidět různé přístupy v zásobníkech volání a také v plánech provádění.
Přímo streamováno
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
S dílčím dotazem
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
Oba nakonec volají stejný základní kód XML, ale „nezabalená“ verze nemá v plánu samotném žádné iterátory XML, výsledku je dosaženo nahrazením volání metody z CXStmtSelect
pomocí CXStmtXMLSelect
místo toho (v plánu reprezentován jako kořenový uzel XML Select spíše než prostý starý uzel Select).
Na SQL Server 2016 CTP3 stále vidím ntext
pro nejvyšší úroveň FOR XML
. Nejvyšší úroveň však FOR JSON
zobrazí se jako nvarchar(max)
Alespoň v CTP název speciálního sloupce JSON stále obsahuje GUID F52E2B61-18A1-11d1-B105-00805F49916B
navzdory skutečnosti, že původem tohoto je rozhraní IXMLDocument.
Plány vypadají téměř stejně, ačkoli XML Select je nahrazen JSON Select
BTW:Na sestavení Microsoft SQL Server 2014 - 12.0.4213.0 (X64)
Nevidím žádný rozdíl v chování mezi dočasnými tabulkami a trvalými tabulkami. To je pravděpodobně způsobeno jinou @@Version
mezi prostředími, která vaše otázka používá http://sqlfiddle.com/ (12.0.2000.8) a https://data.stackexchange.com/ (12.0.4213.0).
Možná byla opravena chyba v sys.dm_exec_describe_first_result_set
mezi dvěma stavbami z roku 2014.
V roce 2012 dostanu stejné výsledky jako Shnugo na 11.0.5343.0 (s NULL
v prvních třech řádcích), ale po instalaci SP3 11.0.6020.0 dostanu stejné výsledky jako vaše počáteční výsledky zobrazené v otázce.