sql >> Databasteknik >  >> RDS >> Sqlserver

VÄLJ FÖR XML AUTO och returnera datatyper

FOR XML introducerades i SQL Server 2000.

SQL Server 2000 hade inte MAX datatyper eller XML data typ. Det var inte heller möjligt att använda FOR XML i en underfråga.

Artikeln Vad returnerar serversidan FOR XML? förklarar

I SQL Server 2000 ... FOR XML ... implementerades i kodlagret mellan frågeprocessorn och datatransportlagret ... frågeprocessorn producerar resultatet på samma sätt som utan FOR XML och sedan FOR XML kod formaterar raduppsättningen som XML. För maximal XML-publiceringsprestanda FOR XML gör ångande XML-formatering av den resulterande raduppsättningen och skickar dess utdata direkt till serversidans TDS-kod i små bitar utan att buffra hela XML i serverutrymmet. Bitstorleken är 2033 UCS-2-tecken. Således skickas XML större än 2033UCS-2 tecken till klientsidan i flera rader som var och en innehåller en bit av XML. SQL Server använder ett fördefinierat kolumnnamn för denna raduppsättning med en kolumn av typen NTEXT -“XML_F52E2B61-18A1-11d1-B105-00805F49916B ” – för att indikera chunked XMLrowset i UTF-16-kodning.

Så det verkar som att detta fortfarande är implementerat på samma sätt för toppnivå FOR XML även i senare versioner.

SQL Server 2005 introducerade möjligheten att använda FOR XML i underfrågor (vilket betyder att dessa nu måste hanteras av frågeprocessorn snarare än ett lager utanför den medan resultaten streamas till klienten)

Samma artikel förklarar att dessa kommer att skrivas som NVARCHAR(MAX) eller XML beroende på närvaron eller inte av en type direktiv.

Förutom skillnaden i datatyp betyder detta den ytterligare SELECT wrapper kan göra en drastisk skillnad i prestanda om #tab är stor.

/*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

Det är möjligt att se de olika tillvägagångssätten i anropsstacken samt genomförandeplaner.

Strömma direkt

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    

Med underfråga

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

Båda anropar samma underliggande XML-kod men den "oupppackade" versionen har inga XML-iteratorer i själva planen, resultatet uppnås genom att ersätta metodanrop från CXStmtSelect med CXStmtXMLSelect istället (representerad i planen som en XML Select-rotnod snarare än en vanlig gammal Select).

På SQL Server 2016 CTP3 ser jag fortfarande ntext för toppnivå FOR XML . Men toppnivå FOR JSON visas som nvarchar(max)

Åtminstone i CTP:n innehåller JSON-specialkolumnnamnet fortfarande GUID F52E2B61-18A1-11d1-B105-00805F49916B trots att ursprunget till detta är IXMLDocument Interface.

Planerna ser ungefär likadana ut även om XML Select ersätts med en JSON Select

BTW:På build Microsoft SQL Server 2014 - 12.0.4213.0 (X64) Jag ser ingen skillnad i beteende mellan temporära tabeller och permanenta tabeller. Detta beror förmodligen på den olika @@Version mellan miljöerna använder din fråga http://sqlfiddle.com/ (12.0.2000.8) och https://data.stackexchange.com/ (12.0.4213.0).

Kanske har ett fel åtgärdats i sys.dm_exec_describe_first_result_set mellan de två 2014-byggen.

2012 får jag samma resultat som Shnugo 11.0.5343.0 (med NULL i de första tre raderna) men efter att ha installerat SP3 11.0.6020.0 får jag samma resultat som dina första resultat som visas i frågan.



  1. MariaDB datum- och tidsenheter

  2. Ställa in en anslutningstimeout med PDO

  3. Utveckla en modul med Java 9 i Eclipse IDE, del 2

  4. Vilka är de 10 bästa funktionerna i Microsoft Access?