{"id":1496,"date":"2012-12-24T10:00:26","date_gmt":"2012-12-24T15:00:26","guid":{"rendered":"http:\/\/sqlity.net\/en\/?p=1496"},"modified":"2014-11-13T13:50:18","modified_gmt":"2014-11-13T18:50:18","slug":"a-join-a-day-predicate-probe-residual","status":"publish","type":"post","link":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/","title":{"rendered":"A Join A Day \u2013 Predicate, Probe &#038; Residual"},"content":{"rendered":"<div>\n<h3>Introduction<\/h3>\n<p>\nThis is the twenty-fourth post in my <a href=\"http:\/\/sqlity.net\/en\/1146\/a-join-a-day-introduction\/\">A Join A Day<\/a> series about SQL Server Joins. Make sure to let me know how I am doing or ask your burning join related questions by leaving a comment below.\n<\/p>\n<p>\nThe different join algorithms have different ways of identifying rows that need to be checked for a possible match. We did look at that in detail over the last three days. Today we are going to look at the details of the actual matching process.\n<\/p>\n<h3>The Probe<\/h3>\n<p>\nTo start out let's take a look at this simple Hash Join query:\n<\/p>\n<div>\n[sql]\nSELECT soh.AccountNumber, sod.OrderQty, sod.UnitPrice<br \/>\nFROM Sales.SalesOrderDetail AS sod<br \/>\nINNER HASH JOIN Sales.SalesOrderHeader AS soh<br \/>\nON sod.SalesOrderID = soh.SalesOrderID;<br \/>\n[\/sql]\n<\/div>\n<p>\nIt produces this execution plan:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key.jpg\" alt=\"hash join with a single column key\" title=\"hash join with a single column key\" width=\"1093\" height=\"573\" class=\"aligncenter size-full wp-image-1503\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key.jpg 1093w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key-300x157.jpg 300w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key-1024x536.jpg 1024w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key-150x78.jpg 150w\" sizes=\"auto, (max-width: 1093px) 100vw, 1093px\" \/><\/a>\n<\/p>\n<p>\nIf you look at the properties for the Hash Join operator you see a \"Hash Key Build\" and a \"Hash Key Probe\". The build hash key is used when the hash index is created. The probe hash key is then used to find the bucket with match candidates in that index for each row from the second input. Each contains the list of columns from one side that use an equality comparison in the join condition. So what happens when there is an inequality column?\n<\/p>\n<h3>The Residual<\/h3>\n<p>\nTo find out let's add an inequality column to our query:\n<\/p>\n<div>\n[sql]\nSELECT soh.AccountNumber, sod.OrderQty, sod.UnitPrice<br \/>\nFROM Sales.SalesOrderDetail AS sod<br \/>\nINNER HASH JOIN Sales.SalesOrderHeader AS soh<br \/>\nON sod.SalesOrderID = soh.SalesOrderID<br \/>\nAND sod.ModifiedDate != soh.ModifiedDate;<br \/>\n[\/sql]\n<\/div>\n<p>\nNow the query has one equality and one inequality column. Remember, that only equality columns can be used for the hash key. So something else needs to happen with the inequality column. The execution plan looks pretty much identical at first:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-hash-join.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-hash-join.jpg\" alt=\"nonequi hash join\" title=\"nonequi hash join\" width=\"1093\" height=\"573\" class=\"aligncenter size-full wp-image-1497\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-hash-join.jpg 1093w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-hash-join-300x157.jpg 300w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-hash-join-1024x536.jpg 1024w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-hash-join-150x78.jpg 150w\" sizes=\"auto, (max-width: 1093px) 100vw, 1093px\" \/><\/a>\n<\/p>\n<p>\nHowever that is now one additional property in the properties list of the Hash Join operator. It is the \"Probe Residual\" and this is its value (with added linebreaks):\n<\/p>\n<div>\n[sourcecode]\n[AdventureWorks2008R2].[Sales].[SalesOrderDetail].[SalesOrderID] as [sod].[SalesOrderID] =<br \/>\n[AdventureWorks2008R2].[Sales].[SalesOrderHeader].[SalesOrderID] as [soh].[SalesOrderID]\nAND<br \/>\n[AdventureWorks2008R2].[Sales].[SalesOrderDetail].[ModifiedDate] as [sod].[ModifiedDate] &lt;&gt;<br \/>\n[AdventureWorks2008R2].[Sales].[SalesOrderHeader].[ModifiedDate] as [soh].[ModifiedDate]\n[\/sourcecode]\n<\/div>\n<p>\nThe Probe Residual property can only be found if there are columns in the join condition that could not be part of the hash key. However, the probe only identifies the correct bucket. To identify all matching rows in there SQL Server has to compare each of them with the current one. This comparison is using the value of the Probe Residual as condition. The Probe residual therefore matches the join condition of the query. This is even the case if there are only equality columns in the condition. In that case the residual is just not spelled out for us.\n<\/p>\n<h3>Where (join columns)<\/h3>\n<p>\nLet's look at the same query with a merge join hint:\n<\/p>\n<div>\n[sql]\nSELECT soh.AccountNumber, sod.OrderQty, sod.UnitPrice<br \/>\nFROM Sales.SalesOrderDetail AS sod<br \/>\nINNER MERGE JOIN Sales.SalesOrderHeader AS soh<br \/>\nON sod.SalesOrderID = soh.SalesOrderID<br \/>\nAND sod.ModifiedDate != soh.ModifiedDate<br \/>\n[\/sql]\n<\/div>\n<p>\nThe execution plan now contains a Merge Join Operator. Its properties look very similar to the ones of the Hash Join operator:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-merge-join.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-merge-join.jpg\" alt=\"nonequi merge join\" title=\"nonequi merge join\" width=\"1093\" height=\"573\" class=\"aligncenter size-full wp-image-1498\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-merge-join.jpg 1093w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-merge-join-300x157.jpg 300w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-merge-join-1024x536.jpg 1024w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/nonequi-merge-join-150x78.jpg 150w\" sizes=\"auto, (max-width: 1093px) 100vw, 1093px\" \/><\/a>\n<\/p>\n<p>\nThe main difference is that the join condition now is not represented by a set of keys, but by a \"Where (join columns)\" section. This section also contains only equality columns. The complete join condition can be found in the \"Residual\" property. The value of the Residual property for above query looks like this:\n<\/p>\n<div>\n[sourcecode]\n[AdventureWorks2008R2].[Sales].[SalesOrderDetail].[SalesOrderID] as [sod].[SalesOrderID] =<br \/>\n[AdventureWorks2008R2].[Sales].[SalesOrderHeader].[SalesOrderID] as [soh].[SalesOrderID]\nAND<br \/>\n[AdventureWorks2008R2].[Sales].[SalesOrderDetail].[ModifiedDate] as [sod].[ModifiedDate] &lt;&gt;<br \/>\n[AdventureWorks2008R2].[Sales].[SalesOrderHeader].[ModifiedDate] as [soh].[ModifiedDate]\n[\/sourcecode]\n<\/div>\n<p>\nOther than with Hash Join operators, this property is present on equi-merge-joins:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/equi-merge-join.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/equi-merge-join.jpg\" alt=\"equi merge join\" title=\"equi merge join\" width=\"1093\" height=\"573\" class=\"aligncenter size-full wp-image-1502\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/equi-merge-join.jpg 1093w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/equi-merge-join-300x157.jpg 300w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/equi-merge-join-1024x536.jpg 1024w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/equi-merge-join-150x78.jpg 150w\" sizes=\"auto, (max-width: 1093px) 100vw, 1093px\" \/><\/a>\n<\/p>\n<p>\nUnsurprising its value is this:\n<\/p>\n<div>\n[sourcecode]\n[AdventureWorks2008R2].[Sales].[SalesOrderHeader].[SalesOrderID] as [soh].[SalesOrderID] =<br \/>\n[AdventureWorks2008R2].[Sales].[SalesOrderDetail].[SalesOrderID] as [sod].[SalesOrderID]\n[\/sourcecode]\n<\/div>\n<p>\nThis makes sense, as the \"join columns\" really are only used to sort the two inputs. The final comparison using the residual is what decides if the two rows are a match or not.\n<\/p>\n<h3>Out of the Loop<\/h3>\n<p>\nAfter looking at the Hash Join and Merge Join operators there is one more left to dissect. It is the Loop Join operator, and with it things are different. But let's look at an example first:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-with-scan-time-filter.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-with-scan-time-filter.jpg\" alt=\"a loop join with a scan time filter\" title=\"a loop join with a scan time filter\" width=\"1093\" height=\"573\" class=\"aligncenter size-full wp-image-1505\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-with-scan-time-filter.jpg 1093w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-with-scan-time-filter-300x157.jpg 300w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-with-scan-time-filter-1024x536.jpg 1024w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-with-scan-time-filter-150x78.jpg 150w\" sizes=\"auto, (max-width: 1093px) 100vw, 1093px\" \/><\/a>\n<\/p>\n<p>\nThis is the same query we have used before, this time with a loop join hint. The properties of the Loop Join operator contain the join condition &mdash; nowhere?! There is no indication on this operator anywhere that would tell us what the join condition is. But if you remember the <a href=\"http:\/\/sqlity.net\/en\/1183\/a-join-a-day-the-cross-join\/\">Cross Join article<\/a>, SQL Server does complain if there is no condition given. That means, as there is no warning in this plan that it did not miss this one's condition. So what happened?\n<\/p>\n<h3>The Predicate<\/h3>\n<p>\nThe data access operator for the <span class=\"tt\">Sales.SalesOrderHeader<\/span> table, which makes the right side input to our join, is a Seek operator. For a seek you need a value to seek for. That search value in an index seek is called \"Seek Predicate\" and you can find it in the properties of the Index Seek operator:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-scan-time-filter.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-scan-time-filter.jpg\" alt=\"loop join scan time filter properties\" title=\"loop join scan time filter properties\" width=\"1093\" height=\"573\" class=\"aligncenter size-full wp-image-1504\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-scan-time-filter.jpg 1093w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-scan-time-filter-300x157.jpg 300w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-scan-time-filter-1024x536.jpg 1024w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/loop-join-scan-time-filter-150x78.jpg 150w\" sizes=\"auto, (max-width: 1093px) 100vw, 1093px\" \/><\/a>\n<\/p>\n<p>\nIt contains this value:\n<\/p>\n<div>\n[sourcecode]\nSeek Keys[1]: Prefix: [AdventureWorks2008R2].[Sales].[SalesOrderHeader].SalesOrderID = Scalar Operator([AdventureWorks2008R2].[Sales].[SalesOrderDetail].[SalesOrderID] as [sod].[SalesOrderID])<br \/>\n[\/sourcecode]\n<\/div>\n<p>\nThis is a little cumbersome to read but it says that the <span class=\"tt\">SalesOrderId<\/span> column in the <span class=\"tt\">Sales.SalesOrderHeader<\/span> need to match that of the <span class=\"tt\">SalesOrderId<\/span> column in the <span class=\"tt\">Sales.SalesOrderDetail<\/span> table. This matches the equality part of our join condition.\n<\/p>\n<p>\nThere is a second property on the Index Seek operator, the \"Predicate\" property. It contains this value:\n<\/p>\n<div>\n[sourcecode]\n[AdventureWorks2008R2].[Sales].[SalesOrderDetail].[ModifiedDate] as [sod].[ModifiedDate] &lt;&gt;<br \/>\n[AdventureWorks2008R2].[Sales].[SalesOrderHeader].[ModifiedDate] as [soh].[ModifiedDate]\n[\/sourcecode]\n<\/div>\n<p>\nThis is just the inequality part of the join condition. So within the Index Seek operator SQL Server directly accesses only rows that are a match in one part of the join condition. Those rows get passed through an additional filter within the same operator that takes care of the second half of the join condition. So, all rows that reach the Nested Loops Join operator are known to be a match already. Therefore that operator does not need to know about the join condition anymore and can just combine all rows coming back from the index seek with the current row from the <span class=\"tt\">Sales.SalesOrderHeader<\/span> table.\n<\/p>\n<p>\nThe columns included in the Seek Predicate are not necessarily all of the equality columns. Instead it is the largest index key prefix that is completely part of the equality section of the index. So if the join condition would be <span class=\"tt\">t1.a = t2.a AND t1.b = t2.b<\/span> and <span class=\"tt\">t2<\/span> had an index on the columns <span class=\"tt\">a, c<\/span> the Seek Predicate would contain just column <span class=\"tt\">a<\/span>.\n<\/p>\n<p>\nThe previous example showed a loop join that was able to make use of an index on the right side table. Let's see what happens if that is not possible. For the purpose of this exercise let's assume we are looking for all <span class=\"tt\">Sales.SalesOrderDetail<\/span> records to a given <span class=\"tt\">Sales.SalesOrderHeader<\/span> row that happened on the same day but are associated with a different order:\n<\/p>\n<div>\n[sql]\nSET ROWCOUNT 50;<\/p>\n<p>SELECT soh.AccountNumber, sod.OrderQty, sod.UnitPrice<br \/>\nFROM Sales.SalesOrderDetail AS sod<br \/>\nINNER LOOP JOIN Sales.SalesOrderHeader AS soh<br \/>\nON sod.SalesOrderID != soh.SalesOrderID<br \/>\nAND sod.ModifiedDate = soh.ModifiedDate;<\/p>\n<p>SET ROWCOUNT 0;<br \/>\n[\/sql]\n<\/p><\/div>\n<p>\nThe two <span class=\"tt\">SET ROWCOUNT<\/span> statement restrict the number of rows coming back from the query in between to 50 rows. I did not want to wait for this query to finish without that restriction.\n<\/p>\n<p>\nThe execution plan for this query looks the same as the one of the previous query with the exception of the arrow thickness:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/reverse-loop-join.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/reverse-loop-join.jpg\" alt=\"loop join with predicate\" title=\"loop join with predicate\" width=\"1093\" height=\"573\" class=\"aligncenter size-full wp-image-1499\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/reverse-loop-join.jpg 1093w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/reverse-loop-join-300x157.jpg 300w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/reverse-loop-join-1024x536.jpg 1024w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/reverse-loop-join-150x78.jpg 150w\" sizes=\"auto, (max-width: 1093px) 100vw, 1093px\" \/><\/a>\n<\/p>\n<p>\nThe properties for the Loop Join operator contain one called \"Predicate\". It contains the following value:\n<\/p>\n<div>\n[sourcecode]\n[AdventureWorks2008R2].[Sales].[SalesOrderDetail].[ModifiedDate] as [sod].[ModifiedDate] =<br \/>\n[AdventureWorks2008R2].[Sales].[SalesOrderHeader].[ModifiedDate] as [soh].[ModifiedDate]\nAND<br \/>\n[AdventureWorks2008R2].[Sales].[SalesOrderDetail].[SalesOrderID] as [sod].[SalesOrderID] &lt;&gt;<br \/>\n[AdventureWorks2008R2].[Sales].[SalesOrderHeader].[SalesOrderID] as [soh].[SalesOrderID]\n[\/sourcecode]\n<\/div>\n<p>\nThis contains the entire join condition with both the equality part and the inequality part. So, all rows from the second input get passed into the join operator in this case to build the complete Cartesian product. The join operator then identifies the matches using the Predicate value.\n<\/p>\n<p>\nThis showed the two extreme examples of Loop Join implementations in SQL Server. Depending on the query anything in between could happen too. Sometimes you even see an additional Filter operator in between the table access operator and the right side input of the Loop Join operator.\n<\/p>\n<h3>Summary<\/h3>\n<p>\nThis article showed the different places where the join condition can be found in a join execution plan. We covered Predicates, Probes and Residuals which are used to identify the matching rows in different places of the plan. Which ones are actually part of a given plan is depending on the join operator used.\n<\/p>\n<h3>A Join A Day<\/h3>\n<p>\nThis post is part of my December 2012 \"A Join A Day\" blog post series. You can find the table of contents with all posts published so far in the introductory post: <a href=\"http:\/\/sqlity.net\/en\/1146\/a-join-a-day-introduction\/\">A Join A Day \u2013 Introduction<\/a>. Check back there frequently throughout the month.\n<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>This article talks about predicates, probes and residuals, all of which are used in different places of different join queries. This knowledge can help you to identify why your join query is slow and where it is spending its time.<\/p>\n<p> <a href=\"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/\">[more&#8230;]<\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[28,5,27,14],"tags":[],"class_list":["post-1496","post","type-post","status-publish","format-standard","hentry","category-a-join-a-day","category-general","category-series","category-sql-server-internals"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>A Join A Day \u2013 Predicate, Probe &amp; Residual - sqlity.net<\/title>\n<meta name=\"description\" content=\"This article talks about predicates, probes and residuals, all of which are used in different places of different join queries. This knowledge can help you to identify why your join query is slow and where it is spending its time.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A Join A Day \u2013 Predicate, Probe &amp; Residual - sqlity.net\" \/>\n<meta property=\"og:description\" content=\"This article talks about predicates, probes and residuals, all of which are used in different places of different join queries. This knowledge can help you to identify why your join query is slow and where it is spending its time.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/\" \/>\n<meta property=\"og:site_name\" content=\"sqlity.net\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/sqlity.net\" \/>\n<meta property=\"article:published_time\" content=\"2012-12-24T15:00:26+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2014-11-13T18:50:18+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key.jpg\" \/>\n<meta name=\"author\" content=\"Sebastian Meine\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@sqlity\" \/>\n<meta name=\"twitter:site\" content=\"@sqlity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Sebastian Meine\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/\"},\"author\":{\"name\":\"Sebastian Meine\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#\\\/schema\\\/person\\\/bcffd8c572bc2f1bd10fdba80135e53c\"},\"headline\":\"A Join A Day \u2013 Predicate, Probe &#038; Residual\",\"datePublished\":\"2012-12-24T15:00:26+00:00\",\"dateModified\":\"2014-11-13T18:50:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/\"},\"wordCount\":1592,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2012\\\/12\\\/hash-join-with-single-key.jpg\",\"articleSection\":[\"A Join A Day\",\"General\",\"Series\",\"SQL Server Internals\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/\",\"url\":\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/\",\"name\":\"A Join A Day \u2013 Predicate, Probe & Residual - sqlity.net\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2012\\\/12\\\/hash-join-with-single-key.jpg\",\"datePublished\":\"2012-12-24T15:00:26+00:00\",\"dateModified\":\"2014-11-13T18:50:18+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#\\\/schema\\\/person\\\/bcffd8c572bc2f1bd10fdba80135e53c\"},\"description\":\"This article talks about predicates, probes and residuals, all of which are used in different places of different join queries. This knowledge can help you to identify why your join query is slow and where it is spending its time.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/#primaryimage\",\"url\":\"http:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2012\\\/12\\\/hash-join-with-single-key.jpg\",\"contentUrl\":\"http:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2012\\\/12\\\/hash-join-with-single-key.jpg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/1496\\\/a-join-a-day-predicate-probe-residual\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/sqlity.net\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"A Join A Day \u2013 Predicate, Probe &#038; Residual\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/sqlity.net\\\/en\\\/\",\"name\":\"sqlity.net\",\"description\":\"Quality for SQL\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/sqlity.net\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#\\\/schema\\\/person\\\/bcffd8c572bc2f1bd10fdba80135e53c\",\"name\":\"Sebastian Meine\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g\",\"caption\":\"Sebastian Meine\"},\"sameAs\":[\"http:\\\/\\\/sqlity.net\",\"https:\\\/\\\/x.com\\\/sqlity\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"A Join A Day \u2013 Predicate, Probe & Residual - sqlity.net","description":"This article talks about predicates, probes and residuals, all of which are used in different places of different join queries. This knowledge can help you to identify why your join query is slow and where it is spending its time.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/","og_locale":"en_US","og_type":"article","og_title":"A Join A Day \u2013 Predicate, Probe & Residual - sqlity.net","og_description":"This article talks about predicates, probes and residuals, all of which are used in different places of different join queries. This knowledge can help you to identify why your join query is slow and where it is spending its time.","og_url":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/","og_site_name":"sqlity.net","article_publisher":"https:\/\/www.facebook.com\/sqlity.net","article_published_time":"2012-12-24T15:00:26+00:00","article_modified_time":"2014-11-13T18:50:18+00:00","og_image":[{"url":"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key.jpg","type":"","width":"","height":""}],"author":"Sebastian Meine","twitter_card":"summary_large_image","twitter_creator":"@sqlity","twitter_site":"@sqlity","twitter_misc":{"Written by":"Sebastian Meine","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/#article","isPartOf":{"@id":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/"},"author":{"name":"Sebastian Meine","@id":"https:\/\/sqlity.net\/en\/#\/schema\/person\/bcffd8c572bc2f1bd10fdba80135e53c"},"headline":"A Join A Day \u2013 Predicate, Probe &#038; Residual","datePublished":"2012-12-24T15:00:26+00:00","dateModified":"2014-11-13T18:50:18+00:00","mainEntityOfPage":{"@id":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/"},"wordCount":1592,"commentCount":0,"image":{"@id":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/#primaryimage"},"thumbnailUrl":"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key.jpg","articleSection":["A Join A Day","General","Series","SQL Server Internals"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/","url":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/","name":"A Join A Day \u2013 Predicate, Probe & Residual - sqlity.net","isPartOf":{"@id":"https:\/\/sqlity.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/#primaryimage"},"image":{"@id":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/#primaryimage"},"thumbnailUrl":"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key.jpg","datePublished":"2012-12-24T15:00:26+00:00","dateModified":"2014-11-13T18:50:18+00:00","author":{"@id":"https:\/\/sqlity.net\/en\/#\/schema\/person\/bcffd8c572bc2f1bd10fdba80135e53c"},"description":"This article talks about predicates, probes and residuals, all of which are used in different places of different join queries. This knowledge can help you to identify why your join query is slow and where it is spending its time.","breadcrumb":{"@id":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/#primaryimage","url":"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key.jpg","contentUrl":"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/12\/hash-join-with-single-key.jpg"},{"@type":"BreadcrumbList","@id":"https:\/\/sqlity.net\/en\/1496\/a-join-a-day-predicate-probe-residual\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/sqlity.net\/en\/"},{"@type":"ListItem","position":2,"name":"A Join A Day \u2013 Predicate, Probe &#038; Residual"}]},{"@type":"WebSite","@id":"https:\/\/sqlity.net\/en\/#website","url":"https:\/\/sqlity.net\/en\/","name":"sqlity.net","description":"Quality for SQL","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/sqlity.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/sqlity.net\/en\/#\/schema\/person\/bcffd8c572bc2f1bd10fdba80135e53c","name":"Sebastian Meine","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g","caption":"Sebastian Meine"},"sameAs":["http:\/\/sqlity.net","https:\/\/x.com\/sqlity"]}]}},"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2wXuw-o8","jetpack-related-posts":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/posts\/1496","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/comments?post=1496"}],"version-history":[{"count":0,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/posts\/1496\/revisions"}],"wp:attachment":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/media?parent=1496"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/categories?post=1496"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/tags?post=1496"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}