FOR XML
đã được giới thiệu trong SQL Server 2000.
SQL Server 2000 không có MAX
kiểu dữ liệu hoặc XML
loại dữ liệu. Cũng không thể sử dụng FOR XML
trong một truy vấn phụ.
Bài viết Phía máy chủ FOR XML trả về gì? giải thích
Trong SQL Server 2000 ...
FOR XML
... được thực hiện trong lớp mã giữa bộ xử lý truy vấn và lớp truyền tải dữ liệu ... bộ xử lý truy vấn tạo ra kết quả theo cách giống như khi không cóFOR XML
rồi đếnFOR XML
mã định dạng tập hợp hàng dưới dạng XML. Để có hiệu suất xuất bảnXML tối đaFOR XML
thực hiện định dạng XML của tập hợp hàng kết quả và gửi trực tiếp đầu ra của nó tới TDScode phía máy chủ theo từng phần nhỏ mà không cần đệm toàn bộ XML trong không gian máy chủ. Kích thước phân đoạn là 2033 ký tự UCS-2. Do đó, các ký tự XML lớn hơn 2033UCS-2 được gửi đến phía máy khách trong nhiều hàng, mỗi hàng chứa một phần của XML. SQL Server sử dụng tên cột được xác định trước cho tập hợp hàng này với một cột thuộc loạiNTEXT
- “XML_F52E2B61-18A1-11d1-B105-00805F49916B
”- để chỉ ra tập hợp XMLrowset được phân khúc trong mã hóa UTF-16.
Vì vậy, có vẻ như điều này vẫn được triển khai theo cùng một cách đối với FOR XML
cấp cao nhất trong các phiên bản mới hơn.
SQL Server 2005 đã giới thiệu khả năng sử dụng FOR XML
trong các truy vấn con (có nghĩa là bây giờ chúng cần được xử lý bởi bộ xử lý truy vấn thay vì một lớp bên ngoài nó trong khi truyền trực tuyến kết quả đến máy khách)
Bài báo tương tự giải thích rằng chúng sẽ được nhập là NVARCHAR(MAX)
hoặc XML
phụ thuộc vào sự hiện diện hay không của một loại type
chỉ thị.
Cũng như sự khác biệt về kiểu dữ liệu, điều này có nghĩa là SELECT
bổ sung trình bao bọc có thể tạo ra sự khác biệt lớn về hiệu suất nếu #tab
lớn.
/*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
Có thể thấy các cách tiếp cận khác nhau trong ngăn xếp cuộc gọi cũng như kế hoạch thực thi.
Được phát trực tiếp
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
Với truy vấn phụ
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
Cả hai đều kết thúc việc gọi cùng một mã XML cơ bản nhưng phiên bản "chưa được gói" không có bất kỳ trình lặp XML nào trong chính kế hoạch, kết quả đạt được bằng cách thay thế các lệnh gọi phương thức từ CXStmtSelect
với CXStmtXMLSelect
thay vào đó (được trình bày trong kế hoạch dưới dạng nút gốc của Lựa chọn XML thay vì một Nút chọn cũ thuần túy).
Trên SQL Server 2016 CTP3, tôi vẫn thấy ntext
cho cấp cao nhất FOR XML
. Tuy nhiên, cấp cao nhất FOR JSON
hiển thị dưới dạng nvarchar(max)
Ít nhất trong CTP, tên cột đặc biệt JSON vẫn chứa GUID F52E2B61-18A1-11d1-B105-00805F49916B
mặc dù thực tế nguồn gốc của điều này là Giao diện tài liệu IXML.
Các kế hoạch trông giống nhau mặc dù Lựa chọn XML được thay thế bằng Lựa chọn JSON
BTW:Trên bản dựng Microsoft SQL Server 2014 - 12.0.4213.0 (X64)
Tôi không thấy bất kỳ sự khác biệt nào về hành vi giữa bảng tạm thời và bảng vĩnh viễn. Đây có thể là do @@Version
khác nhau giữa các môi trường mà câu hỏi của bạn sử dụng http://sqlfiddle.com/ (12.0.2000.8) và https://data.stackexchange.com/ (12.0.4213.0).
Có thể một lỗi đã được sửa trong sys.dm_exec_describe_first_result_set
giữa hai bản dựng năm 2014.
Vào năm 2012, tôi nhận được kết quả tương tự như Shnugo trên 11.0.5343.0 (với NULL
trong ba hàng đầu tiên) nhưng sau khi cài đặt SP3 11.0.6020.0, tôi nhận được kết quả giống như kết quả ban đầu của bạn được hiển thị trong câu hỏi.