MPD
MPD

Reputation: 605

Are SELECT FOR XML querys slow?

I have a stored procedure which returns XML to the caller using a SELECT FOR XML PATH statement. As more rows have been added to the main table in the query I have noticed that the performance of this query has degraded.

On investigation I found that running the query in SQL management studio without the FOR XML statement takes the 1/3 of the time the FOR XML query takes. Is the XML generation that is invoked by FOR XML that much of an overhead or are there some do's and don't s when using FOR XML.

Below is my table definition and the query used which returns > 3000 rows. The column names have been changed to protect the innocent.

Any advice would be welcome.

CREATE TABLE dbo.results
( 
colA  int NOT NULL, 
colB  varchar(20) NULL, 
colC varchar(30) NULL, 
colD varchar(100) NULL, 
colE char(3) NULL, 
colF int NULL, 
colG int NULL, 
colH datetime NULL, 
colJ int NULL, 
colK int NULL, 
colL int NULL, 
colM int NULL, 
colN int NULL, 
colO int NULL, 
colP int NULL, 
colQ int NULL, 
colR int NULL, 
colS int NULL, 
colT int NULL, 
colU int NULL, 
colV int NULL, 
colW int NULL, 
colX int NULL, 
colY datetime NULL, 
colZ int NULL, 
colA1 datetime NULL, 
colB1 int NULL, 
colC1 int NULL, 
colD1 int NULL, 
colE1 int NULL, 
colF1 int NULL, 
colG1 int NULL, 
colH1 int NULL, 
colI1 int NULL, 
colK1 int NULL, 
colL1 int NULL, 
colM1 int NULL, 
colN1 int NULL, 
colO1 int NULL, 
colP1 int NOT NULL, 
colQ1 int NOT NULL, 
colS1 int NULL, 
colT1 int NULL, 
colU1 int NULL, 
colV1 int NULL, 
colW1 int NULL, 
colX1 int NULL, 
colY1 int NULL, 
colZ1 datetime NULL 

CONSTRAINT results_pk PRIMARY KEY CLUSTERED 
( 
   colA ASC 
)
WITH (PAD_INDEX  = OFF, 
      STATISTICS_NORECOMPUTE  = OFF, 
      IGNORE_DUP_KEY = OFF, 
      ALLOW_ROW_LOCKS  = ON, 
      ALLOW_PAGE_LOCKS  = ON) 
 ON PRIMARY) 

Query:

select    colA  "@A", 
          colB "@B", 
          colC "@C", 
          colD "@D", 
          colE "@E", 
          colF "@F", 
          colG "@G",                      
          colH "@H",         
          colJ "@J", 
          colK "@K",            
          colL "@L", 
          colM "@M", 
          colO "@O", 
          colN "@N", 
          colP "@P", 
          colQ "@Q", 
          colR "@R", 
          colZ1 "@Z1", 
          colS "@S", 
          colT "@T", 
          colU "@U", 
          colV "@V", 
          colW "@W", 
          colX "@X", 
          colY "@Y", 
          colP1 "@P1", 
          colQ1 "@Q1", 
          colO1 "@O1" 
from result
order by colO desc , colC 
for xml PATH('item'), TYPE 

Upvotes: 3

Views: 7386

Answers (2)

Ben Thul
Ben Thul

Reputation: 32737

Just to make sure that you're not taking client rendering time into the equation, assign the result to a variable and see if the execution time is the same. Here's an example I just ran on my server:

SET STATISTICS TIME ON
go

DECLARE @x XML
PRINT '------------'
SELECT @x =
(SELECT * FROM sys.[dm_exec_connections] AS dec
FOR XML PATH('connections'), TYPE)
PRINT '------------'

SELECT * FROM sys.[dm_exec_connections] AS dec
FOR XML PATH('connections'), TYPE

And here are the results (looking at the execution times):

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 87 ms.
------------

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 34 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 2 ms.
------------

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 15 ms,  elapsed time = 884 ms.

Putting it in a variable took 34+2=36 ms whereas dumping it to my screen took 884. That's quite a difference!

Upvotes: 3

Yuck
Yuck

Reputation: 50865

In my experience, that's just the way it is - slow. We get used to working with set-based SQL and are spoiled by how efficient it is. XML isn't there yet. It's implemented as a CLR type in SQL Server which adds another layer of overhead to the equation.

Your example is about as simple as it gets; there isn't a silver bullet that will make it much quicker once you're working with larger sets of data. On that note, must you return entire data sets (3k records) as XML? Can you retrieve only a portion and grab the rest if it's needed?

Upvotes: 1

Related Questions