【问题标题】:SQL Server: Joining by primary key or using separate queries?SQL Server:通过主键加入还是使用单独的查询?
【发布时间】:2012-11-05 17:30:30
【问题描述】:

关于连接两个表与使用 2 个单独查询的二分法,我有一个简单的问题。

我希望找到一个现有的问题,但我的搜索结果并不多(大多数问题都是针对更复杂的问题)。

例如,考虑两个表 A 和 X,其架构非常简单:

Table A   +-------------+-------------+-------------+
          | Column A (*)| Column X(FK)| Column C    |
          +-------------+-------------+-------------+

Table X   +-------------+-------------+-------------+
          | Column X (*)| Column Y    | Column Z    |
          +-------------+-------------+-------------+

其中列 A 和 X 是标识列和主键 (bigint)。表 A 和表 X 之间还存在 X 列的现有外键关系。

我的问题是,假设两个表都足够大(仅说 500K 行),我是否会从使用单个查询(参见下面的 Linq2Sql 伪代码)或使用两个单独的查询中获得更多的性能?

选项 1:

long aValue = 107;
DataContext dc = new DataContext();
var items = (from a in dc.TableA
             join x in dc.TableX
             on a.X equals x.X
             where a.A == aValue
             select new { a, x });

选项 2:

  • 假设我编写了一个 SP,它串行执行 2 个单独的选择语句。

为了进一步量化问题,可以假设对于A的每一个值,只有少数(0-5)行将从表Y中连接,因此连接中返回的表A数据的重复不是意义重大。

我从数据库服务器影响的角度严格要求。因此,忽略任何客户端考虑因素(例如往返网络延迟、L2S 查询构建和数据编组成本等),我的问题是:

  1. 哪个选项在数据库服务器上的计算时间更短?

  2. 哪个选项需要更少的内存来评估结果?

  3. 如果有最佳实践,通常首选哪个选项?

对不起,如果这听起来太初级,但任何见解都会受到赞赏。

谢谢, - K.

【问题讨论】:

    标签: sql-server performance inner-join


    【解决方案1】:

    嗯,根据我在繁忙的数据库中的经验,运行两个不连接的查询总是比一个带连接的查询好。

    这两种方法总是有一个区别:当您加入时,SQL 必须以某种方式匹配行(当预测返回的行数较少时,可能使用嵌套循环)。当工作量或结果集很大时,它就开始变得重要了。

    如果您不希望您的数据库成为瓶颈,并且此连接以某种方式简化了开发,那么请继续。


    为了在更大的表上为您提供任何数字,我尝试了两种针对我管理的数据库上的父表和子表的方法。它们分别有 150k 行和 3000k 行。 SQL 打印这些统计信息:

    加入查询

    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 7 ms.
    Table 'child'. Scan count 1, logical reads 324, physical reads 0, read-ahead reads 0.
    Table 'parent'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0.
    
    SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 70 ms.
    

    单独选择

    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 0 ms.
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 0 ms.
    Table 'parent'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0.
    
    SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 0 ms.
    
    (1 row(s) affected)
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 0 ms.
    Table 'child'. Scan count 1, logical reads 324, physical reads 0, read-ahead reads 0.
    
    SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 1 ms.
    

    (表有适当的索引;表名已更改)

    【讨论】:

      【解决方案2】:

      简答:相信优化器。

      针对索引良好的表的单个查询(尤其是简单的连接)将比编写一组串行 SQL 语句更有效。我不是 LINQ 方面的专家,因此我不确定您将使用伪代码返回哪些列,但如果表在适当的硬件上正确索引,您会没事的。

      【讨论】:

      • 太棒了。谢谢斯图尔特。这就是我的想法,并希望如此。
      猜你喜欢
      • 2019-10-21
      • 2011-04-25
      • 2021-01-07
      • 2012-09-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多