Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server 2005性能:WHERE in语句中的独立表或完整表_Sql Server_Database_Performance - Fatal编程技术网

Sql server SQL Server 2005性能:WHERE in语句中的独立表或完整表

Sql server SQL Server 2005性能:WHERE in语句中的独立表或完整表,sql-server,database,performance,Sql Server,Database,Performance,我们有两张桌子: 文档:id、标题、文档类型、显示id DocumentType:id,name 关系:DocumentType有许多文档。Document.Document\u type\u id=DocumentType.id 我们希望检索一个给定ShowOn_Id的所有文档类型的列表 我们看到两种可能性: SELECT DocumentType.* FROM DocumentType WHERE DocumentType.id IN ( SELECT DISTINCT Docume

我们有两张桌子:

文档:id、标题、文档类型、显示id DocumentType:id,name 关系:DocumentType有许多文档。Document.Document\u type\u id=DocumentType.id 我们希望检索一个给定ShowOn_Id的所有文档类型的列表

我们看到两种可能性:

SELECT DocumentType.*
FROM DocumentType
WHERE DocumentType.id IN (
    SELECT DISTINCT Document.document_type_id FROM Document WHERE showon_id = 42
);

SELECT DocumentType.*
FROM DocumentType
WHERE DocumentType.id IN (
    SELECT Document.document_type_id FROM Document WHERE showon_id = 42
);
我们的问题是:何时和是否使用DISTINCT来获取较小的记录集,比检索整个表和在表中遍历到第一个匹配项的IN语句更好。我们猜它就是这样做的-

对于不同的数据库,这是不同的吗?有共同的答案吗

还是有更好的方法?我们在.NET land中

您可以使用连接:

SELECT DISTINCT DocumentType.*
FROM DocumentType
INNER JOIN Document
ON DocumentType.id=Document.document_type_id
WHERE Document.showon_id = 42

我认为这是最好的方法。

从我的观点来看,它在SQL Server内部不应该有任何区别,但谁知道这是如何实现的


可以这样想:要返回结果集,服务器需要进入Document表并检索所有Document_type_id,其中shown_id=42。在检索文档_type _id的过程中(例如通过索引查找),会将其放入哈希表中。此过程完成后,哈希表仍将包含不同的值。之后,查询执行进入Document_Type表,扫描主键并探测哈希表。请注意,这取决于,例如,当文档表中的预期行数比文档类型低时,不使用哈希表可能更有效,但通常您会得到与刚才建议的查询wmasm相同的查询计划。

使用EXISTS。它有时速度更快,但在我看来,它比一个DISTINCT和JOIN更具可读性。只是为了好玩,请回复这个查询的查询计划和上面的连接,看看是否有什么不同,他们可能会优化到相同的计划。如果它们相同,我建议使用EXISTS,因为它更接近纯语言描述,而不是JOIN,因为您不需要来自文档等的任何数据

SELECT whatever
  FROM DocumentType dt
 WHERE EXISTS( SELECT *
                 FROM Document 
                WHERE dt.id     = document_type_id
                  AND showon_id = 42)
要获取查询计划参考,请执行以下操作:

后续行动:

我已经启用了查询计划,并测试了迄今为止出现的四种不同查询:

选择DocumentType.*从DocumentType中选择DocumentType.id,从showon\u id=42的文档中选择DISTINCT Document.Document\u type\u id

选择DocumentType.*从DocumentType中选择Document.Document\u type\u id从shown\u id=42的文档中选择Document.Document\u type\u id

从DocumentType.id=Document.Document\u type\u id其中Document.shown\u id=42的DocumentType内部连接文档中选择DISTINCT DocumentType.*

选择DocumentType.*从存在的DocumentType中选择*从DocumentType.id=Document.Document\u type\u id和showon\u id=42的文档

所有四个查询的查询计划都是相同的:

 |--Hash Match(Right Semi Join, HASH:([Document].[document_type_id])=([DocumentType].[Id]))
       |--Hash Match(Inner Join, HASH:([Document].[Title], [Uniq1005])=([Document].[Title], [Uniq1005]), RESIDUAL:([Document].[Title] as [Document].[Title] = [Document].[Title] as [Document].[Title] AND [Uniq1005] = [Uniq1005]))
       |    |--Index Seek(OBJECT:([Document].[IX_Document_3] AS [Document]), SEEK:([Document].[showon_id]=(1)) ORDERED FORWARD)
       |    |--Index Scan(OBJECT:([Document].[IX_Document_1] AS [Document]))
       |--Table Scan(OBJECT:([DocumentType] AS [DocumentType]))

我不确定每一行和每一个元素都意味着什么,但从性能的角度来看,如何构造这种问题的查询似乎并不重要

为了获得最佳性能,您应该使用:

SELECT DISTINCT dt.* 
FROM 
    DocumentType dt
    INNER JOIN Document d ON dt.id=d.document_type_id and d.showon_id = 42
联接在桥接多个表时非常有效,因为where子句中的嵌套查询需要执行单独的结果选择,该选择将过滤From子句结果。join语句也更具可读性

除了主键和外键关系之外,我还会在showon_id上添加索引


我的答案与wmasm的答案不同,只是将showon_id筛选器上移到内部联接。对于MS SQL 2k5,我认为解释器足够聪明,可以自动执行此操作,但您总是希望使用尽可能小的结果集。当将多个表连接在一起时,将过滤器提升到内部联接语句可以限制查询必须处理的行数。如果您这样做,您应该了解每行比较都会发生这种情况,因此最好将复杂的筛选器(如x='%a'或函数调用)留给Where子句,以便内部联接可以过滤掉不必要的比较。

谢谢,这可能是解决此问题的最简单方法。。。这个查询也比IN子查询快吗?正如ligged78指出的,您也发现了,如果查询计划返回不同的东西,我会非常惊讶。毕竟,性能必须基于您的表/索引设计,而不是查询语法。是的,两个查询的结果集应该相同。所以问题是:服务器是否会自己过滤掉重复的值,过滤是否会对性能产生影响?如果是,使用DISTINCT时是否会以相同的方式进行过滤?->同样,您可以尝试测量所有类型查询的数据性能。有关工具,请参阅。
SELECT DISTINCT dt.* 
FROM 
    DocumentType dt
    INNER JOIN Document d ON dt.id=d.document_type_id and d.showon_id = 42