<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Development Archives - Blog IT</title>
	<atom:link href="https://blogit.create.pt/tag/development/feed/" rel="self" type="application/rss+xml" />
	<link>https://blogit.create.pt/tag/development/</link>
	<description>Create IT blogger community</description>
	<lastBuildDate>Thu, 10 Jan 2019 12:46:01 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>
	<item>
		<title>Query performance for JSON objects inside SQL Server using JSON_VALUE function</title>
		<link>https://blogit.create.pt/goncalomelo/2018/12/20/query-performance-for-json-objects-inside-sql-server/</link>
					<comments>https://blogit.create.pt/goncalomelo/2018/12/20/query-performance-for-json-objects-inside-sql-server/#comments</comments>
		
		<dc:creator><![CDATA[Gonçalo Melo]]></dc:creator>
		<pubDate>Thu, 20 Dec 2018 09:39:12 +0000</pubDate>
				<category><![CDATA[Sql Server]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://blogit.create.pt/?p=8077</guid>

					<description><![CDATA[<p>Following up on this article about querying JSON Data I would like to talk about how to improve searches on JSON data inside SQL Server. Starting SQL Server 2016 Microsoft deployed a set of functions that allow us to work with JSON data in a structured way inside SQL Server. I will introduce a small [&#8230;]</p>
<p>The post <a href="https://blogit.create.pt/goncalomelo/2018/12/20/query-performance-for-json-objects-inside-sql-server/">Query performance for JSON objects inside SQL Server using JSON_VALUE function</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Following up on <a href="https://blogit.create.pt////diogoguiomar/2018/02/26/query-a-json-array-column-in-sql/">this article about querying JSON Data</a> I would like to talk about how to improve searches on JSON data inside SQL Server. Starting SQL Server 2016 Microsoft deployed a set of functions that allow us to work with JSON data in a structured way inside SQL Server.</p>



<p>I will introduce a small usage sample for the <strong>JSON_VALUE </strong>function in combination with indexes to improve information retrieval from a table containing one JSON object. For our testes, we have a <strong>UserDetailTest </strong>table that has more than 500k rows with 2 columns: an UserId and a nvarchar(max) to hold a small JSON details string like the following:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
SELECT *, LEN(DetailsJSON) AS &#x5B;Len(DetailsJSON)] FROM UserDetailTest
</pre></div>


<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="937" height="188" src="https://blogit.create.pt////wp-content/uploads/2018/12/sampleTable.png" alt="" class="wp-image-8153" srcset="https://blogit.create.pt/wp-content/uploads/2018/12/sampleTable.png 937w, https://blogit.create.pt/wp-content/uploads/2018/12/sampleTable-300x60.png 300w, https://blogit.create.pt/wp-content/uploads/2018/12/sampleTable-768x154.png 768w, https://blogit.create.pt/wp-content/uploads/2018/12/sampleTable-696x140.png 696w" sizes="(max-width: 937px) 100vw, 937px" /></figure>



<p>I will activate time statistics and clean SQL Server cache between each query to have some consistency across the execution times using the following SQL statements:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
CHECKPOINT
DBCC DROPCLEANBUFFERS
SET STATISTICS TIME ON
</pre></div>


<h2 class="wp-block-heading">JSON_VALUE Function intro</h2>



<p>The JSON_VALUE function extracts a value from a JSON string. This functions receives 2 arguments, the first being an expression for the JSON value and the second a path for the value we want to obtain. A simple sample with an inline JSON object would be the following:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
SELECT JSON_VALUE('{"PostalCode":"376-3765","PhoneNumber":"351003765718"}', '$.PhoneNumber')
</pre></div>


<figure class="wp-block-image"><img decoding="async" width="1245" height="123" src="https://i1.wp.com/blogit.create.pt/wp-content/uploads/2018/12/selectResult0.png?fit=696%2C69&amp;ssl=1" alt="" class="wp-image-8182" srcset="https://blogit.create.pt/wp-content/uploads/2018/12/selectResult0.png 1245w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult0-300x30.png 300w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult0-768x76.png 768w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult0-1024x101.png 1024w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult0-696x69.png 696w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult0-1068x106.png 1068w" sizes="(max-width: 1245px) 100vw, 1245px" /></figure>



<p>The return is a scalar value (nvarchar(4000)) for the PhoneNumber element.</p>



<h2 class="wp-block-heading">Query scenarios</h2>



<p>Starting with one of the <strong>really&nbsp;worst </strong>case scenario (yes, this can happen&#8230;):</p>



<figure class="wp-block-image"><img decoding="async" width="1024" height="240" src="https://blogit.create.pt////wp-content/uploads/2018/12/selectResult20-1024x240.png" alt="" class="wp-image-8197" srcset="https://blogit.create.pt/wp-content/uploads/2018/12/selectResult20-1024x240.png 1024w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult20-300x70.png 300w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult20-768x180.png 768w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult20-696x163.png 696w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult20-1068x250.png 1068w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult20.png 1275w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>More than 17 seconds really seems like a worst scenario! Next, we will use the JSON_VALUE function to get the PhoneNumber from the JSON string and use it in our where clause:</p>



<figure class="wp-block-image"><img decoding="async" width="1266" height="301" src="https://i1.wp.com/blogit.create.pt/wp-content/uploads/2018/12/selectResult22.png?fit=696%2C165&amp;ssl=1" alt="" class="wp-image-8198" srcset="https://blogit.create.pt/wp-content/uploads/2018/12/selectResult22.png 1266w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult22-300x71.png 300w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult22-768x183.png 768w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult22-1024x243.png 1024w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult22-696x165.png 696w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult22-1068x254.png 1068w" sizes="(max-width: 1266px) 100vw, 1266px" /></figure>



<p>This still takes more than 3 seconds. A good improvement, but yet a high cost if we need to search information in this way.</p>



<h2 class="wp-block-heading" id="mce_9">Index creation</h2>



<p>Let&#8217;s add a new virtual column to table that displays the result from the JSON_VALUE function &#8211; this will allow us to create an index and simplify the SELECT queries.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
ALTER TABLE UserDetailTest 
	ADD vPhoneNumber AS 
	CAST(JSON_VALUE(DetailsJSON, '$.PhoneNumber') AS NVARCHAR(255));
</pre></div>


<p>The cast truncates the output from the JSON_VALUE&nbsp;to ensure that it does not exceed the maximum lenght for the index key. Now, if we search using the column, the result is still more or less the same 3 seconds has before:</p>



<ul class="wp-block-gallery columns-1 is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex"><li class="blocks-gallery-item"><figure><img decoding="async" width="1274" height="311" src="https://i1.wp.com/blogit.create.pt/wp-content/uploads/2018/12/selectResult23.png?fit=696%2C170&amp;ssl=1" alt="" data-id="8199" data-link="https://blogit.create.pt////?attachment_id=8199" class="wp-image-8199" srcset="https://blogit.create.pt/wp-content/uploads/2018/12/selectResult23.png 1274w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult23-300x73.png 300w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult23-768x187.png 768w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult23-1024x250.png 1024w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult23-696x170.png 696w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult23-1068x261.png 1068w" sizes="(max-width: 1274px) 100vw, 1274px" /></figure></li></ul>



<p>Let&#8217;s create an index and perform the search again:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
CREATE INDEX idx_vPhoneNumber ON &#x5B;UserDetailTest] (vPhoneNumber);

</pre></div>


<ul class="wp-block-gallery columns-1 is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex"><li class="blocks-gallery-item"><figure><img decoding="async" width="1270" height="316" src="https://i1.wp.com/blogit.create.pt/wp-content/uploads/2018/12/selectResult24.png?fit=696%2C173&amp;ssl=1" alt="" data-id="8201" data-link="https://blogit.create.pt////?attachment_id=8201" class="wp-image-8201" srcset="https://blogit.create.pt/wp-content/uploads/2018/12/selectResult24.png 1270w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult24-300x75.png 300w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult24-768x191.png 768w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult24-1024x255.png 1024w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult24-696x173.png 696w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult24-1068x266.png 1068w" sizes="(max-width: 1270px) 100vw, 1270px" /></figure></li></ul>



<p>Consequently the improvement is huge, 13 miliseconds is more interesting! But what&#8217;s the cost?</p>



<h2 class="wp-block-heading">The cost</h2>



<p>When we create an index, we&#8217;re basically trading space for time &#8211; more occupied space versus faster operations. Therefore let&#8217;s see what the increase is using&nbsp;<strong>sp_spaceused</strong> function before and after index creation:</p>



<table class="wp-block-table is-style-regular"><tbody><tr><td></td><td><strong>rows</strong></td><td><strong>reserved</strong></td><td><strong>data</strong></td><td><strong>index_size</strong></td><td><strong>unused</strong></td></tr><tr><td><strong>Initial</strong></td><td>557801              </td><td>1120904 KB</td><td>1115584 KB</td><td>5224 KB</td><td>96 KB</td></tr><tr><td><strong>After Index</strong></td><td>557801</td><td>1148752 KB</td><td>1115584 KB</td><td>32992 KB</td><td>176 KB</td></tr></tbody></table>



<p>Probably, an interesting comparison would be if the PhoneNumber column was an explicit column in that table containing the value. Let&#8217;s do that!</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
ALTER TABLE UserDetailTest  
	ADD PhoneNumberCopy NVARCHAR(255)

UPDATE UserDetailTest
	SET PhoneNumberCopy = vPhoneNumber
</pre></div>


<p>The sp_spaceused remained the same &#8211; SQL Server internal black magic regarding space allocation (for another time!). But performance wise, for this approach in my machine this query still took more than 2 seconds to complete:</p>



<figure class="wp-block-image"><img decoding="async" width="1269" height="362" src="https://i2.wp.com/blogit.create.pt/wp-content/uploads/2018/12/selectResult26.png?fit=696%2C198&amp;ssl=1" alt="" class="wp-image-8203" srcset="https://blogit.create.pt/wp-content/uploads/2018/12/selectResult26.png 1269w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult26-300x86.png 300w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult26-768x219.png 768w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult26-1024x292.png 1024w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult26-696x199.png 696w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult26-1068x305.png 1068w" sizes="(max-width: 1269px) 100vw, 1269px" /></figure>



<p>Slightly better than the query with the JSON function but the advantage is that in this scenario SQL can better optimize the searches. The following runs of the same query without clearing the cache returns results much faster &#8211; each took around 220 miliseconds to complete:</p>



<figure class="wp-block-image"><img decoding="async" width="1263" height="343" src="https://i2.wp.com/blogit.create.pt/wp-content/uploads/2018/12/selectResult27.png?fit=696%2C189&amp;ssl=1" alt="" class="wp-image-8204" srcset="https://blogit.create.pt/wp-content/uploads/2018/12/selectResult27.png 1263w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult27-300x81.png 300w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult27-768x209.png 768w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult27-1024x278.png 1024w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult27-696x189.png 696w, https://blogit.create.pt/wp-content/uploads/2018/12/selectResult27-1068x290.png 1068w" sizes="(max-width: 1263px) 100vw, 1263px" /></figure>



<h2 class="wp-block-heading">Summary Results</h2>



<p>Just to sum up all the results for the different types of searches comparing the first execution after cache clean up and the following runs.&nbsp;I did several iterations for each step just to make sure the results were consistent&nbsp;although the goal was just to have a baseline. Certanly, the use of this will depend on each case.</p>



<table class="wp-block-table"><tbody><tr><td><strong>WHERE clausule type</strong></td><td><strong>First run</strong></td><td><strong>Following runs</strong></td></tr><tr><td><pre class="brush: sql; gutter: false; title: ; notranslate">WHERE DetailsJson LIKE '%PhoneNumber&quot;:&quot;351003765718&quot;%'</pre></td><td>17754 ms</td><td>around the same</td></tr><tr><td><pre class="brush: sql; gutter: false; title: ; notranslate">WHERE JSON_VALUE(DetailsJson, '$.PhoneNumber') = '351003765718'</pre></td><td>3375 ms</td><td>1958 ms</td></tr><tr><td><pre class="brush: sql; gutter: false; title: ; notranslate">WHERE vPhoneNumber = '351003765718'</pre>vPhoneNumber is not indexed&nbsp;</td><td>3339 ms</td><td>1332 ms</td></tr><tr><td><pre class="brush: sql; gutter: false; title: ; notranslate">WHERE vPhoneNumber = '351003765718'</pre> vPhoneNumber is indexed</td><td>13 ms</td><td>0 ms</td></tr><tr><td><pre class="brush: sql; gutter: false; title: ; notranslate">WHERE PhoneNumberCopy  = '351003765718'</pre>PhoneNumberCopy&nbsp; is of type nvarchar(255) and explicitly contains all values</td><td>2309 ms</td><td>222 ms</td></tr></tbody></table>



<p></p>
<p>The post <a href="https://blogit.create.pt/goncalomelo/2018/12/20/query-performance-for-json-objects-inside-sql-server/">Query performance for JSON objects inside SQL Server using JSON_VALUE function</a> appeared first on <a href="https://blogit.create.pt">Blog IT</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blogit.create.pt/goncalomelo/2018/12/20/query-performance-for-json-objects-inside-sql-server/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
	</channel>
</rss>
