select Posts.Title, Users.DisplayName
From Posts JOIN Users on
Posts.OwnerUserId = Users.Id
OPTION (MAXDOP 1)
据我所知,顶部索引扫描的结果变为具有哈希功能,并且底部索引簇扫描的每一行都被查找。我了解散列表在至少某种程度上是如何工作的,但是在这样的示例中,我对哪些值确切地被散列感到困惑。
对我来说有意义的是它们之间的公共字段,即id进行哈希处理-但是如果是这种情况,为什么还要哈希一个数字?
#1 楼
作为SQLRockstar的答案,最适合大型未分类的输入。
现在,从Users.DisplayName索引扫描(假定为非聚集)中,得到的是Users.Id(假定为聚集的)=未排序的
您还正在扫描OwnerUserId = unsorted
的帖子,这是2个无序的输入。
我会考虑OwnerUserId的Posts表上的索引,包括Title。这将在输入的一侧向JOIN +添加一些顺序,它将覆盖索引
CREATE INDEX IX_OwnerUserId ON Posts (OwnerUserId) INCLUDE (Title)
然后您可能会发现Users.DisplayName索引不会被使用,它将扫描PK。
#2 楼
摘自http://sqlinthewild.co.za/index.php/2007/12/30/execution-plan-operations-joins/“哈希联接是较昂贵的联接操作之一,因为它需要创建一个哈希表来进行联接。也就是说,对于大型的,未排序的输入来说,联接是最好的。这是所有联接中最消耗内存的
join首先读取输入中的一个,然后对join列进行哈希处理,然后将结果哈希和列值放入内存中建立的哈希表中,然后读取第二个输入中的所有行,对这些行进行哈希处理并检查结果中的行连接到该行的哈希桶。”
链接到该帖子:
http://blogs.msdn.com/b/craigfr/archive/2006/08/ 10 / 687630.aspx
HTH
评论
因此,如果仅仅是id字段,我想我不了解散列id字段的优势吗?
–凯尔·勃兰特(Kyle Brandt)
2011年3月23日在22:19
+1指向Craig Freedman博客的链接,还有更多可用的加入文章:blogs.msdn.com/b/craigfr/archive/tags/joins
–杰夫
2011-3-24在1:55
#3 楼
对数字字段进行哈希处理的好处是,您可以采用更大的值并将其分解为较小的部分,以便可以将其放入哈希表中。Grant Fritchey的描述方式如下:
“另一方面,哈希表是一种数据结构,可将所有元素划分为大小相等的类别或存储桶,以便快速访问这些元素。哈希函数确定例如,您可以从表中获取一行,将其哈希为哈希值,然后将哈希值存储到哈希表中。”
您还可以获取的免费副本他的电子书“剖析SQL Server执行计划”来自以下文章的链接:
来源:http://www.simple-talk.com/sql/performance/graphical-execution-plans-for -simple-sql-queries /
评论
关于JOINS的另一个有趣的文章系列:sql-server-performance.com/articles/dba/…
–杰夫
2011-3-24在2:10
我通过剖析SQL Server执行计划来工作-太好了!但是我在这一点上有点卡住了:-P
–凯尔·勃兰特(Kyle Brandt)
2011年3月24日13:09
直接链接到电子书
–woodvi
16年11月17日在16:23
评论
好的,我现在知道了,我在想Users.DisplayName已由PK排序,事实并非如此。现在对我来说,使用Hash更加有意义。谢谢!
–凯尔·勃兰特(Kyle Brandt)
2011-3-24在13:01
您也可以尝试OPTION(FAST n)提示,其中n是您期望的大致行数。这将使优化器偏向嵌套循环,而不是在n为低时进行哈希联接。原因是散列连接对于大型连接来说速度很快,但是启动成本很高。嵌套循环每行昂贵,但是可以很便宜地开始。因此,这取决于您的实际数据和访问模式进行微调。
– Gaius
2011-3-28 11:42
@Gaius:就个人而言,我宁愿有索引而不是提示。提示仅在您添加查询时才有用。又名提示随着时间的流逝成为一种责任。索引往往有用得多。
– gbn
11年3月28日在11:50
这不是一个非此即彼的主张:-)
– Gaius
2011年3月28日在11:51