理解在SQL Server

时间:2016-07-11 13:41:12

标签: sql-server

我已经对查询集进行了测试以查看性能。我发现没有聚集索引的查询很快,为什么......?

查询在

下面

从table1中选择A.col1,B.col2,B.col3 A.col1 = B.col1上的内连接table2

表现

哈希匹配(两者都没有索引或没有索引)

(913271排受影响) 表'表B'。扫描计数5,逻辑读取18681,物理读取193,预读读取18681,lob

逻辑读取0,lob物理读取0,lob预读读取0。 表'表B'。扫描计数5,逻辑读取57798,物理读取4,预读读取57798,lob逻辑读取0,lob

物理读取0,lob预读读取0。 表'工作台'。扫描计数0,逻辑读取0,物理读取0,预读取读取0,lob逻辑读取0,lob物理

读取0,lob预读读取0。

(1行受影响)

SQL Server执行时间:    CPU时间= 3665 ms,经过时间= 9391 ms。

总时间:09秒

enter image description here

合并加入:(两者都有唯一的非聚集索引)

(913271排受影响) 表'表B'。扫描计数1,逻辑读取18723,物理读取6,预读读取18727,lob

逻辑读取0,lob物理读取0,lob预读读取0。 表'表B'。扫描计数1,逻辑读取56811,物理读取21,预读读取56921,lob逻辑读取0,lob

物理读取0,lob预读读取0。

(1行受影响)

SQL Server执行时间:    CPU时间= 1466 ms,经过时间= 14881 ms。 SQL Server解析和编译时间:

总时间:14秒

enter image description here

2 个答案:

答案 0 :(得分:1)

两种索引类型的相对性能取决于在各种表中的值分布。两种索引类型都支持允许它们避免读取新块的情况,和/或能够重新使用已经缓存的块,以便有利地利用"预读"策略,等等。但是,他们执行此操作的实用能力取决于数据,以及正在执行的特定操作。

您的应用程序设计的一部分应该是务实的检查,以确定一种方法(如果有的话)"明确是否优于其他方法"在 y-o-u-r 的情况。但是,确实没有"事实获胜者。" (如果有,"其他"索引类型很久以前就会被抛弃。)

"单一,孤立的资源消耗测试"是不够的:你必须考虑所有角度,包括执行各种操作所需的时间(不仅仅是一个),数据量的影响等等等等。

答案 1 :(得分:1)

我觉得这里有两个问题。要阅读并理解Merge vs Hash连接的内容,请参阅MSDN文档。然而,我看到的第二个问题是你滥用SQL Server并试图理解查询计划之间的区别。

我会回答第二个问题(谷歌“Hash Join”回答第一个问题)。查询性能取决于用于连接列的数据类型和页面中的项目数。

但是!!这里最重要的是你正在倾倒整个表(我看到上面的并行连接图标,这让我想到了一个糟糕的查询)。因此,SQL Server正试图找到最快的方式游泳整个事情并抽出数据。我的问题---您的应用程序是否真的意味着转储所有数据?或者JOIN或WHERE子句会有更多内容吗?您正在尝试针对非现实查询进行优化。

您所看到的是基于数据分布的统计(直方图)生成的不同查询计划。出于某种原因,SQL Server“认为”该计划是最好的。数据显然存在偏差,SQL Server认为(平均而言)扫描整个表以完成工作(更少的I / O成本)更快。如果数据集很小 - 那么SQL Server认为转储数据比处理以下索引要快。或者没有可用的索引看起来会有所帮助(在这种情况下---你正在转储所有数据 - 所以SQL Server很可能更喜欢Clustered索引,如果存在,在某些情况下最窄的索引,因为I / O将最小的。)

当索引丢失时(一个堆表) - SQL Server没有任何东西可以继续并转储表并使工作失明。尝试在主键上创建聚簇索引。虽然 - 在这种特殊情况下,它可能无济于事,因为您正在转储所有数据。

需要考虑的其他事项:“col1”中的值是唯一的(1:1,或1:*)....还是n:n?您需要在创建表时声明这一点(创建唯一索引或主键)。此信息是SQL Server“学习”有关未来数据的一种方式。您所做的一切都是将您的意图传达给SQL Server的方法,以便它可以做正确的事情。

现在我将继续定义你的表和索引(仅在需要时 - 从主键开始) - 写一些真实的查询(可能添加索引) - 然后查看你的结果。否则你就会过早地进行优化。

索引的(一般)规则是:尽可能少地使用尽可能少的列 - 从而最大限度地提高使用率。索引是在向表中添加或修改数据时必须更新的结构。因此,更多的索引和大量的列将最终减慢你的速度。你只需要你想要的东西 - 而不是更多。另见 - 3只小熊的故事。

SQL Server的另一个规则 - 具有聚簇索引。堆表被认为是“糟糕的”。是的,有一个堆的论据 - 但恕我直言,这是一个400级的讨论。要开始 - 声明PK和群集。

祝你好运。