October 4, 2005 at 3:51 am
Hi all.
During some code optimisation I found a bit of XML manipulation that, according to the query plan, takes over 50% of a 7 sec query.
I'm not particuarly experienced with XML, so I'm not sure if it cam be improved and if so, how.
Anyone with XML experience that's willing to lend a hand?
CREATE TABLE #ParameterFilter (localname varchar(1000) PRIMARY KEY,Value varchar(1000))
DECLARE @xml VARCHAR(2000)
SET @xml='<FilterString><Sender /><OurReference /><Reference>PT21 </Reference><Direction /><Type /><Host /></FilterString>'
DECLARE @idoc int
EXEC sp_xml_preparedocument @idoc OUTPUT, @ParameterFilter
DECLARE @TempXML TABLE (
ID int PRIMARY KEY,
ParentID int,
NodeType int,
LocalName VARCHAR(1000),
Value ntext
)
INSERT INTO @TempXML
SELECT [id],ParentId,NodeType, localname, text as Value
FROM OPENXML (@idoc, '')
EXEC sp_xml_removedocument @idoc
INSERT INTO #ParameterFilter
SELECT ColumnName.localname, CAST(ColumnValue.[Value] AS VARCHAR(1000))
FROM @TempXML DataRow INNER JOIN
@TempXML ColumnName ON DataRow.Id = ColumnName.Parentid INNER JOIN
@TempXML ColumnValue ON ColumnName.Id = ColumnValue.Parentid
WHERE (DataRow.localname = 'FilterString')
Thanks in advance.
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
October 4, 2005 at 6:24 am
My first question would be why are you using xml and what are you trying to do exactly?
My second question is can you drop the xml part of the equation??
October 4, 2005 at 7:46 am
Can't drop the xml, short of rewriting the entire front end app (which isn't an option) and large portions of the back-end code
Basically (and very simplified), the front-end app calls a generic stored proc to return data. The stored proc takes as parameters the name of the table/view and an xml string which acts as a filter. The XML is read and converted to a where clause. The example I posted would equate to
WHERE Reference='PT21'
I'm mainly wondering (since I've worked very little with XML) if there's an faster way to convert the xml into a list of 'parameters' and values (which is what the Parameterfilter table is)
Thanks
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
October 4, 2005 at 8:00 am
if there's an faster way to convert the xml into a list of 'parameters' and values (which is what the Parameterfilter table is)
Yes there is but you need to be more specific with the description of the the XML data that your example uses. Or at least I don't understand the logic for that "where clause generation".
You should be able to insert directly into the parameters table using the right xpath!
* Noel
October 4, 2005 at 8:11 am
I posted an example:
<FilterString><Sender /><OurReference /><Reference>PT21 </Reference><Direction /><Type /><Host /></FilterString>
Another example:
<FilterString><Status /><Sender /><Reference /><AccountNo /><DateFrom>2005-09-01</DateFrom><DateTo>2005-09-28</DateTo></FilterString>
It's the way the front end passes an array of parameters to SQL, so the only thing that's constant is the outer node (Filterstring) The subnodes depend on the table been queried and where in the front end the query is coming from.
Got a nasty feeling that I'm stuck doing it this way until SQL 2005
btw, xpath in SQL 2000?
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
October 4, 2005 at 8:42 am
Yes XPath in SQL 2000
FROM BOL:
OPENXML(idoc int [in],rowpattern nvarchar[in],[flags byte[in]])
[WITH (SchemaDeclaration | TableName)]
idoc
Is the document handle of the internal representation of an XML document. The internal representation of an XML document is created by calling sp_xml_preparedocument.
rowpattern
Is the XPath pattern used to identify the nodes (in the XML document whose handle is passed in the idoc parameter) to be processed as rows.
flags
Indicates the mapping that should be used between the XML data and the relational rowset, and how the spill-over column should be filled. flags is an optional input parameter, and can be one of these values.
Because it is dynamic they simply used the edge table instead!
It would have being more intuitive to use TableName columnName and Columnvalues as ELEMENTS on the XML to have a "Fixed" pattern
Cheers,
* Noel
October 5, 2005 at 2:16 am
Thanks, that's good to know. This is the first time I'm working with xml in SQL. Haven't touched xml since I was doing webdev some years back.
Agreed, name and value elements in the xml would have been much cleaner. I'll chat with the front-end developers, see if anything can be done.
Otherwise, rollon SQL 2005.
Thanks.
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
October 6, 2005 at 3:17 am
I think you can simplify the query a bit too using xpath in the WITH clause...
set nocount on
DECLARE @xml VARCHAR(2000)
DECLARE @ParameterFilter TABLE(localname varchar(1000), value varchar(1000))
DECLARE @idoc int
SET @xml='<FilterString><Sender /><OurReference /><Reference>PT21 </Reference><Direction /><Type /><Host /></FilterString>'
EXEC sp_xml_preparedocument @idoc OUTPUT, @xml
INSERT INTO @ParameterFilter
SELECT localname, value
FROM OPENXML (@idoc, '/FilterString/node()')
WITH ( localname varchar(1000) '@mp:localname',
value varchar(1000) 'text()'
)
WHERE value is not NULL
EXEC sp_xml_removedocument @idoc
select * from @ParameterFilter
set nocount off
October 13, 2005 at 4:36 am
That works great. Thank you very much.
Would you mind explaining what/how the xpath works there?
Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability
October 13, 2005 at 5:14 am
bol description of OPENXML:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_oa-oz_5c89.asp
OPENXML (@idoc, '/FilterString/node()')
produces a table from the doc, using the xpath provided - this just says that each row is a match for any node under FilterString under root, i.e. the children of FilterString.
the WITH clause just gives names to the fields - @mp:localname is described in the bol ref - here it just gives the name of each node we match, and text() is just the text of that node.
Hope that helps
Jon
Viewing 10 posts - 1 through 9 (of 9 total)
You must be logged in to reply to this topic. Login to reply