<?xml version="1.0" encoding="UTF-8"?>
<!--Generated by Squarespace Site Server v5.8.3 (http://www.squarespace.com/) on Fri, 27 Nov 2009 15:27:23 GMT--><feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><title>Journal</title><subtitle>Journal</subtitle><id>http://josef-richberg.squarespace.com/journal/</id><link rel="alternate" type="application/xhtml+xml" href="http://josef-richberg.squarespace.com/journal/"/><link rel="self" type="application/atom+xml" href="http://josef-richberg.squarespace.com/journal/atom.xml"/><updated>2009-11-27T03:01:19Z</updated><generator uri="http://www.squarespace.com/" version="Squarespace Site Server v5.8.3 (http://www.squarespace.com/)">Squarespace</generator><entry><title>Ownership chaining or how to extend permissions without giving away the server</title><category term="chaining"/><category term="ownership"/><category term="views"/><id>http://josef-richberg.squarespace.com/journal/2009/11/26/ownership-chaining-or-how-to-extend-permissions-without-givi.html</id><link rel="alternate" type="text/html" href="http://josef-richberg.squarespace.com/journal/2009/11/26/ownership-chaining-or-how-to-extend-permissions-without-givi.html"/><author><name>Josef Richberg</name></author><published>2009-11-27T03:00:54Z</published><updated>2009-11-27T03:00:54Z</updated><content type="html" xml:lang="en-US"><![CDATA[<p>The nightly process in our production system collects data from our real time systems (JD Edwards) and then processes that data. &nbsp;Many of these process manipulate the data and supply a modified data set for use by the dozens of client processes and applications. &nbsp;All of the client applications have their own databases (tables, views, procedures, etc), but due to the nature of the 'raw' data we collect (we have over 350 million rows of historical and current data) sometimes the client apps need to directly access this. &nbsp;It would be too costly to replicate this data for each individual application that would need it as well as maintaining dozens of copies would be impossible. &nbsp;This posed a unique problem:How do you grant access to the raw data in limited format?</p>
<p>The reason for the limited format is some of the data is for the ETL process only and if used by an application would provide false or erroneous data (one of our tables has over 250 columns). &nbsp;After a bit of research we came up with the following mechanism to allow specific access to specific tables in specific databases, with the added benefit of not having to add every new id to the permission roster.</p>
<p>First thing that needs to be done is to make sure that the same owner owns the files of the databases you are looking to chain. &nbsp;To simplify our servers, all files are owned by SA. &nbsp;This prevents the situation where a user id was used to create or restore a database, but they are no longer with us. &nbsp;Here is where you set that up:</p>
<p>&nbsp;</p>
<p><span class="full-image-block ssNonEditable"><span><img style="width: 150px;" src="http://josef-richberg.squarespace.com/storage/cross_chaining_1.png?__SQUARESPACE_CACHEVERSION=1259246328503" alt="" /></span></span></p>
<p>Second&nbsp;thing we need to do is turn on '<strong>database cross-chaining</strong>'. &nbsp;This enables permissions to be transferred when you have statements that cross databases, such as being in database <strong>A</strong> and doing the following: <strong>select * from B.dbo.sometable</strong>. &nbsp;This causes sql server to validate the user who is in database A to have permission to select from the table 'sometable' in database <strong>B</strong>. &nbsp;You turn on database cross chaining as follows:<strong> sp_dboption &lt;database_name&gt;,'db chain','ON'. &nbsp;</strong>This should be done in both databases, that is the database you are calling from and the database you are looking to access. &nbsp;In the above scenario, you would turn it on in <strong>A </strong>and <strong>B</strong>.</p>
<p>Third thing to be done is: <strong>grant connect to guest</strong>&nbsp;in both databases. &nbsp;This is the mechanism that SQL Server uses to pass credentials.</p>
<p>The next step is we create views in the 'source' database, which in the above example would be in the <strong>B</strong>&nbsp;database. &nbsp;Then you create a corresponding view in the application database, <strong>A</strong>. &nbsp;This does two things. &nbsp;First as you add users to the application databases you need not add them to any of the <strong>source</strong>&nbsp;databases, since they will be calling local views. &nbsp;Second, it provides a way to seal off the applications and as we add new sources of information, we simply create local views and hence isolate all applications from the <strong>Common</strong>&nbsp;data, keeping it pristine and from prying eyes.</p>
<p>I do realize the applications have to go through two views, the local view and then the view in the <strong>source</strong>&nbsp;database. &nbsp;Some have asked if this has a noticeable performance impact and I cannot say it does. &nbsp;The security flexibility we get from the above design far out ways any performance detriment as the apps run well within the time allotted (many sub-second).</p>
<p><strong><br /></strong></p>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></content></entry><entry><title>Head on over to SQL University</title><id>http://josef-richberg.squarespace.com/journal/2009/11/25/head-on-over-to-sql-university.html</id><link rel="alternate" type="text/html" href="http://josef-richberg.squarespace.com/journal/2009/11/25/head-on-over-to-sql-university.html"/><author><name>Josef Richberg</name></author><published>2009-11-26T02:11:53Z</published><updated>2009-11-26T02:11:53Z</updated><content type="html" xml:lang="en-US"><![CDATA[<p>Jorge Segarra (<a href="http://www.twitter.com/SQLChicken">twitter</a>) has put together a wonderful collection of sql articles known as 'SQL University'. &nbsp;This is a place that all levels of sql practitioners should bookmark and go to. &nbsp;I am happy and honored to announce that I have been selected as one of the faculty members. &nbsp;Head on over and take a gander, you won't be disappointed. &nbsp;The link to <a href="http://sqlchicken.com/SQL-university/">SQL University</a>.</p>]]></content></entry><entry><title>Index Primer - Just what statistics are kept?</title><id>http://josef-richberg.squarespace.com/journal/2009/11/25/index-primer-just-what-statistics-are-kept.html</id><link rel="alternate" type="text/html" href="http://josef-richberg.squarespace.com/journal/2009/11/25/index-primer-just-what-statistics-are-kept.html"/><author><name>Josef Richberg</name></author><published>2009-11-25T23:42:26Z</published><updated>2009-11-25T23:42:26Z</updated><content type="html" xml:lang="en-US"><![CDATA[<p>Here is a link to my article on sqlservercentral. &nbsp;Thank you Steve Jones (<a href="http://www.twitter.com/way0utwest">twitter</a>) for the guidance and opportunity.</p>
<p><a href="http://www.sqlservercentral.com/articles/Optimizer/68141/">Index Primer</a></p>]]></content></entry><entry><title>Linked to the Microsoft SSIS Documentation Portal</title><category term="MSDN"/><id>http://josef-richberg.squarespace.com/journal/2009/11/25/linked-to-the-microsoft-ssis-documentation-portal.html</id><link rel="alternate" type="text/html" href="http://josef-richberg.squarespace.com/journal/2009/11/25/linked-to-the-microsoft-ssis-documentation-portal.html"/><author><name>Josef Richberg</name></author><published>2009-11-25T20:41:26Z</published><updated>2009-11-25T20:41:26Z</updated><content type="html" xml:lang="en-US"><![CDATA[<p>I am thrilled to announce that my blog has been linked to the Microsoft SSIS portal page. &nbsp;This information was sent to me late September and I was unable to blog at that time. &nbsp;Special thanks to &nbsp;Douglas Laudenschlager of the Microsoft SSIS documentation team. &nbsp;Here is the link: <a href="http://msdn.microsoft.com/en-us/sqlserver/cc511477.aspx">portal</a></p>]]></content></entry><entry><title>Where I've been..</title><id>http://josef-richberg.squarespace.com/journal/2009/11/25/where-ive-been.html</id><link rel="alternate" type="text/html" href="http://josef-richberg.squarespace.com/journal/2009/11/25/where-ive-been.html"/><author><name>Josef Richberg</name></author><published>2009-11-25T13:14:44Z</published><updated>2009-11-25T13:14:44Z</updated><content type="html" xml:lang="en-US"><![CDATA[<p>This isn't a technical post, yet I believe the community deserves an answer as to where I've been for the last 75 days. &nbsp;I am home now and getting back into the swing of things. &nbsp;I originally went into the hospital for a severe back spasm, which turned out to be caused by a cancer known as Multiple Myeloma. &nbsp;The MM, presented in my spine, causing weakness in certain vertebrae. &nbsp;The muscle spams were caused by lytic lesions, which are basically small fractures, which impinged on a few nerves and hence the spams. &nbsp;With good doctors, shear force of will, a loving family, caring friends, a supportive community (a special thanks to Wibke Weilacher and the Exceptional DBA staff at RedGate), and countless prayers from those I know and those I don't, I have come a long way. &nbsp;My physical recovery has come farther in a faster period of time than the doctors had anticipated and my cancer is being pushed out at a fantastic rate. &nbsp;In the past 75 days a key protein indicator has shown a 34% reduction. &nbsp;I still have a long way to go, but this time I go with friends and family. &nbsp;You will begin to see me back to blogging and twittering. &nbsp;I have a lot of catching up to do.</p>
<p>Thank you everyone!</p>]]></content></entry><entry><title>Long time overdue.</title><id>http://josef-richberg.squarespace.com/journal/2009/10/9/long-time-overdue.html</id><link rel="alternate" type="text/html" href="http://josef-richberg.squarespace.com/journal/2009/10/9/long-time-overdue.html"/><author><name>Josef Richberg</name></author><published>2009-10-09T22:41:23Z</published><updated>2009-10-09T22:41:23Z</updated><content type="html" xml:lang="en-US"><![CDATA[<p>My apologies for taking such a long time to post this. &nbsp;Had a little spill about 3 weeks back and it put me in the hospital. &nbsp;I guess the gardening and horsing around with my son finally took a toll on my back. &nbsp;I am finally able to get online and will start blogging soon (once I get back into the swing of things). &nbsp;Also, being that I am still in the hospital they seem to have twitter blocked (go figure). &nbsp;I am actively working on getting back to it and back to the community, which is why you haven't seen me out there for the last few weeks. &nbsp;I so do miss it. &nbsp;Hope to 'see' you all there soon.</p>]]></content></entry><entry><title>I am honored to be giving a virtual presentation for PASS.</title><category term="sqlpass"/><id>http://josef-richberg.squarespace.com/journal/2009/9/20/i-am-honored-to-be-giving-a-virtual-presentation-for-pass.html</id><link rel="alternate" type="text/html" href="http://josef-richberg.squarespace.com/journal/2009/9/20/i-am-honored-to-be-giving-a-virtual-presentation-for-pass.html"/><author><name>Josef Richberg</name></author><published>2009-09-21T01:11:11Z</published><updated>2009-09-21T01:11:11Z</updated><content type="html" xml:lang="en-US"><![CDATA[<p>Thanks to Thomas LaRock (<a href="http://twitter.com/SQLRockstar">twitter</a>)&nbsp;for introducing me to Jeremiah Peschka (<a href="http://twitter.com/peschkaj">twitter</a>), who took the time to review my presentation and give it the stamp of approval. &nbsp;I will be giving my virtual presentation on SSIS thread load balancing October 13th at 1pm EST. &nbsp;<a href="http://appdev.sqlpass.org/">http://appdev.sqlpass.org/</a>&nbsp;has all the information.</p>]]></content></entry><entry><title>Comments Welcome.</title><category term="Comments"/><id>http://josef-richberg.squarespace.com/journal/2009/9/17/comments-welcome.html</id><link rel="alternate" type="text/html" href="http://josef-richberg.squarespace.com/journal/2009/9/17/comments-welcome.html"/><author><name>Josef Richberg</name></author><published>2009-09-17T12:50:57Z</published><updated>2009-09-17T12:50:57Z</updated><content type="html" xml:lang="en-US"><![CDATA[<p>I made a change in the configuration of my web page to allow anonymous comments. &nbsp;Writing in a vacuum doesn't help anyone.</p>]]></content></entry><entry><title>Indexes and Convert_Implicit</title><category term="conversion"/><category term="implicit"/><category term="index"/><id>http://josef-richberg.squarespace.com/journal/2009/9/16/indexes-and-convert_implicit.html</id><link rel="alternate" type="text/html" href="http://josef-richberg.squarespace.com/journal/2009/9/16/indexes-and-convert_implicit.html"/><author><name>Josef Richberg</name></author><published>2009-09-16T13:54:44Z</published><updated>2009-09-16T13:54:44Z</updated><content type="html" xml:lang="en-US"><![CDATA[<p>When you are designing your where clause to access data from a given set of tables it would benefit you to pay careful attention to the data types of the columns you will be using.&nbsp; SQL Server tries to help out by implicitly converting between data types which can cause 'hidden' optimizer issues.</p>
<p>A common example is the implicit conversion between character and integer datatypes.&nbsp; Listed below is a snippet of the query I was asked to tune.</p>
<p><span class="thumbnail-image-block ssNonEditable"><span><a href="javascript:showFullImage('/display/ShowImage?imageUrl=%2Fstorage%2Fimplicit_join_before.png%3F__SQUARESPACE_CACHEVERSION%3D1253110603748',30,514);"><img src="http://josef-richberg.squarespace.com/storage/thumbnails/4173822-4165507-thumbnail.jpg?__SQUARESPACE_CACHEVERSION=1253110603748" alt="" /></a></span></span></p>
<p>&nbsp;You will notice the number 45 in purple.&nbsp; The graphical query plan produced this:</p>
<p><span class="thumbnail-image-block ssNonEditable"><span><a href="javascript:showFullImage('/display/ShowImage?imageUrl=%2Fstorage%2Fimplicit_showplan.png%3F__SQUARESPACE_CACHEVERSION%3D1253110708718',94,287);"><img src="http://josef-richberg.squarespace.com/storage/thumbnails/4173822-4165529-thumbnail.jpg?__SQUARESPACE_CACHEVERSION=1253110708718" alt="" /></a></span></span></p>
<p>&nbsp;What first drew my attention was that 90% of the time was being taken up by a very small part of the overall where clause.&nbsp; Digging deeper I saw this:</p>
<p>&nbsp;<span class="thumbnail-image-block ssNonEditable"><span><a href="javascript:showFullImage('/display/ShowImage?imageUrl=%2Fstorage%2Fimplicit_showplan_detail.png%3F__SQUARESPACE_CACHEVERSION%3D1253110953784',381,298);"><img src="http://josef-richberg.squarespace.com/storage/thumbnails/4173822-4165535-thumbnail.jpg?__SQUARESPACE_CACHEVERSION=1253110953784" alt="" /></a></span></span></p>
<p>&nbsp;Highlighted in purple was the culprit.&nbsp; A quick look at the column dbo.stcsmf11.hlvno showed it was a char(2), yet in the where clause I was joining it as a number <strong>stcsmf11.hlvno=45</strong>.&nbsp; I changed the where clause to be:</p>
<p><span class="thumbnail-image-block ssNonEditable"><span><a href="javascript:showFullImage('/display/ShowImage?imageUrl=%2Fstorage%2Fimplicit_join_after.png%3F__SQUARESPACE_CACHEVERSION%3D1253111125814',35,518);"><img src="http://josef-richberg.squarespace.com/storage/thumbnails/4173822-4165576-thumbnail.jpg?__SQUARESPACE_CACHEVERSION=1253111125814" alt="" /></a></span></span></p>
<p>&nbsp;</p>
<p>The subtle change in the where clause (making the number (45) into a character ('45')), yields a dramatic improvement.&nbsp; The time spent in that specific section of code goes from 90% to 2%:</p>
<p><span class="thumbnail-image-block ssNonEditable"><span><a href="javascript:showFullImage('/display/ShowImage?imageUrl=%2Fstorage%2Fimplicit_showplan_cor.png%3F__SQUARESPACE_CACHEVERSION%3D1253111897408',112,298);"><img src="http://josef-richberg.squarespace.com/storage/thumbnails/4173822-4165699-thumbnail.jpg?__SQUARESPACE_CACHEVERSION=1253111897408" alt="" /></a></span></span></p>
<p>The detailed picture shows two important pieces of information.&nbsp; First, we are doing an Index Seek vs. an Index Scan and secondly we have an additional join now being used.&nbsp; The join you see was always there, but due to the implicit conversion, SQL Server was not able to use the other qualifier.&nbsp; The additional seek predicate is <strong>00779081.hlval.</strong></p>
<p><span class="thumbnail-image-block ssNonEditable"><span><a href="javascript:showFullImage('/display/ShowImage?imageUrl=%2Fstorage%2Fimplicit_showplan_detail_cor.png%3F__SQUARESPACE_CACHEVERSION%3D1253112183410',408,298);"><img src="http://josef-richberg.squarespace.com/storage/thumbnails/4173822-4165733-thumbnail.jpg?__SQUARESPACE_CACHEVERSION=1253112183410" alt="" /></a></span></span></p>
<p>&nbsp;It is very important to remember to be as specific as possible in your where clauses and keep a close eye on data types.</p>]]></content></entry><entry><title>Procedures, Parameters, and the Optimizer</title><category term="SARG"/><category term="optimizer"/><category term="parameters"/><category term="stored procedure"/><id>http://josef-richberg.squarespace.com/journal/2009/9/9/procedures-parameters-and-the-optimizer.html</id><link rel="alternate" type="text/html" href="http://josef-richberg.squarespace.com/journal/2009/9/9/procedures-parameters-and-the-optimizer.html"/><author><name>Josef Richberg</name></author><published>2009-09-09T15:08:54Z</published><updated>2009-09-09T15:08:54Z</updated><content type="html" xml:lang="en-US"><![CDATA[<p>The stored procedure is a very powerful tool and if you follow a few rules, it will perform very fast and efficiently.</p>
<h3>Rule 1: Do not change parameters that are SARGS.</h3>
<h3>Rule2: If you must break Rule 1, split your procedures.</h3>
<p>Let's create a procedure to use in our examples:</p>
<p><span class="thumbnail-image-block ssNonEditable"><span><a href="javascript:showFullImage('/display/ShowImage?imageUrl=%2Fstorage%2Fprocs_params_optimizer_blog.png%3F__SQUARESPACE_CACHEVERSION%3D1252518079411',377,557);"><img src="http://josef-richberg.squarespace.com/storage/thumbnails/4173822-4097217-thumbnail.jpg?__SQUARESPACE_CACHEVERSION=1252518079413" alt="" /></a></span></span></p>
<p>A little pubishing industry background. &nbsp;ISBN10 was a 10 character identifier used for all books. &nbsp;The industry started running out of available ISBNS, so a new ISBN13 was introduced. &nbsp;There is a formula to convert between ISBN10 &amp; ISBN13 and many legacy applications still rely upon ISBN10. &nbsp;Now let's dig into <strong>RULE1</strong>.</p>
<p>There are two input parameters for this procedure:<strong>@ISBN</strong> and <strong>@discount</strong>, but only 1 of them is a <strong>SARG</strong>. &nbsp;The statement below breaks the first rule by modifying the parameter that is a <strong>SARG: @ISBN</strong>. &nbsp;It does this in the following sql:</p>
<p><strong>SELECT @ISBN=</strong></p>
<p><strong>&nbsp;&nbsp; dbo.udf_CnvISBN13_to_ISBN10(@ISBN)</strong></p>
<p>Why does this matter? &nbsp;The optimizer must first calculate all of the query plans prior to executing the procedure itself, so the above sql statement happens <strong>AFTER</strong>&nbsp;the plans have been determined. &nbsp;If I pass in the <strong>ISBN=&nbsp;</strong>'9780486438511', the optimizer will look to use that value to join to <strong>Book.ISBN</strong>. &nbsp;The optimizer chooses the query plan, runs and then wham! &nbsp;You are now looking for <strong>ISBN</strong>='0486438511'<strong>&nbsp;</strong>and the optimizer most likely picked a wrong plan, which will lead to poor performance.</p>
<p>You notice that I have mentioned nothing about the modification of <strong>@discount</strong>. &nbsp;That's because it is not used as a <strong>SARG</strong>&nbsp;and the optimizer isn't going to use it in determining the query plans.</p>
<p>If due to certain restrictions the application is passing in an ISBN3 and you must convert it to an ISBN10, you use <strong>RULE 2</strong></p>
<p><strong><span class="thumbnail-image-block ssNonEditable"><span><a href="javascript:showFullImage('/display/ShowImage?imageUrl=%2Fstorage%2Fpost-images%2Fprocs_params_optimizer_inner_blog.png%3F__SQUARESPACE_CACHEVERSION%3D1252588585149',457,554);"><img src="http://josef-richberg.squarespace.com/storage/thumbnails/4173822-4105976-thumbnail.jpg?__SQUARESPACE_CACHEVERSION=1252588585152" alt="" /></a></span></span><br /></strong></p>
<p>As you can see from the above image, I have broken the stored procedure into two different procedures. &nbsp;The first procedure merely does the conversion of the ISBN and override of the discount before passing it on to the 'inner' procedure. &nbsp;When the inner procedure is executed, the optimzer will have the correct information and will grab the most efficient query plan, based upon the data passed in.</p>]]></content></entry></feed>