SQL Server逻辑查询处理—它如何管理庞大的数据集?

SQL Server逻辑查询处理—它如何管理庞大的数据集?,sql,sql-server,Sql,Sql Server,我正在阅读有关SQL Server性能的内容: 我遇到的一件令人惊讶的事情是它如何处理逻辑处理中的“FROM”阶段。据我所知,SQL Server将执行以下操作: 1) 对于前两个表,它将创建一个虚拟表(VT1),由两个表的笛卡尔连接组成 2) 对于每个附加表,它将创建VT1和附加表的笛卡尔连接,结果将变成VT1 我敢肯定,在封面下还有很多内容,但从表面上看,如果您处理的是大表(和大查询),这似乎需要大量的处理/内存 我只是想知道是否有人能快速解释一下SQL Server是如何在任何一种现实的

我正在阅读有关SQL Server性能的内容:

我遇到的一件令人惊讶的事情是它如何处理逻辑处理中的“FROM”阶段。据我所知,SQL Server将执行以下操作:

1) 对于前两个表,它将创建一个虚拟表(VT1),由两个表的笛卡尔连接组成

2) 对于每个附加表,它将创建VT1和附加表的笛卡尔连接,结果将变成VT1

我敢肯定,在封面下还有很多内容,但从表面上看,如果您处理的是大表(和大查询),这似乎需要大量的处理/内存


我只是想知道是否有人能快速解释一下SQL Server是如何在任何一种现实的时间/空间框架中做到这一点的?

实际上,优化者会查看整个查询、估计的行、统计数据、约束等

从逻辑上讲,它是按照前面提到的顺序进行的

人为的例子:

SELECT
   BT.col1, LT.col2
FROm
   BigTable BT
   JOIN
   LT.Table LT ON BT.FKCol = LT.PKCol
WHERE
   LT.PKCol = 2
ORDER BY
   BT.col1
BT和LT的笛卡尔坐标可能是1亿

但乐观主义者:

  • 知道PKCol是唯一的,因此它只需要一行
  • 可以使用统计信息估计来自BT的行数
  • 查找索引(例如,在BT上覆盖FKCol的索引,包括col1)
  • 可能会首先应用WHERE
  • 例如,将查找ORDER BY或GROUP BY,以查看它是否可以节省一些假脱机(重新处理)

实际上,优化者将查看整个查询、估计行、统计信息、约束条件等

从逻辑上讲,它是按照前面提到的顺序进行的

人为的例子:

SELECT
   BT.col1, LT.col2
FROm
   BigTable BT
   JOIN
   LT.Table LT ON BT.FKCol = LT.PKCol
WHERE
   LT.PKCol = 2
ORDER BY
   BT.col1
BT和LT的笛卡尔坐标可能是1亿

但乐观主义者:

  • 知道PKCol是唯一的,因此它只需要一行
  • 可以使用统计信息估计来自BT的行数
  • 查找索引(例如,在BT上覆盖FKCol的索引,包括col1)
  • 可能会首先应用WHERE
  • 例如,将查找ORDER BY或GROUP BY,以查看它是否可以节省一些假脱机(重新处理)

如果您真的对SQL Server的工作方式感兴趣,请阅读本书:

如果您真的对SQL Server的工作方式感兴趣,请阅读本书:
我不知道您正在阅读的资源,但您描述的是以下行为:

SELECT ... FROM tableA, tableB, tableC, ....
这使用笛卡尔连接(也称为交叉连接),并且非常昂贵。对于足够大的数据集,SQL Server(或任何RDBMS)无法在任何现实的时间/空间框架内实现这一点

使用ON子句并指定联接类型的性能要好得多:

SELECT ... FROM tableA JOIN tableB on tableB.a_id = tableA.a_id

在实际应用中,交叉连接应该很少,或者至少限于非常小的数据集。对于许多应用程序来说,从不交叉连接并不少见。

我不知道您正在阅读的资源,但您描述的是以下行为:

SELECT ... FROM tableA, tableB, tableC, ....
这使用笛卡尔连接(也称为交叉连接),并且非常昂贵。对于足够大的数据集,SQL Server(或任何RDBMS)无法在任何现实的时间/空间框架内实现这一点

使用ON子句并指定联接类型的性能要好得多:

SELECT ... FROM tableA JOIN tableB on tableB.a_id = tableA.a_id

在实际应用中,交叉连接应该很少,或者至少限于非常小的数据集。对于许多应用程序来说,不进行交叉连接并不少见。

carthesian连接只是对结果的描述,而不是实际结果。在表A、B、C…X的完全carthesian联接之后,将应用过滤运算符(仍作为定义),例如联接的子句和查询的WHERE子句。最后,这个定义又被转换成一个执行计划,其中将包含物理调用操作符,如嵌套循环、散列连接或合并连接,并且这个操作符在迭代时将按照查询定义中的要求生成结果


所以大的100x100x100。。。carthesian多维数据集永远不会具体化,它只是一个定义。

carthesian连接只是对结果的描述,而不是实际结果。在表A、B、C…X的完全carthesian联接之后,将应用过滤运算符(仍作为定义),例如联接的子句和查询的WHERE子句。最后,这个定义又被转换成一个执行计划,其中将包含物理调用操作符,如嵌套循环、散列连接或合并连接,并且这个操作符在迭代时将按照查询定义中的要求生成结果


所以大的100x100x100。。。carthesian多维数据集永远不会被物化,它只是一个定义。

笛卡尔连接(从我所知)发生在执行查询时的“幕后”(即使使用“ON”子句)。这发生在查询处理的“FROM”阶段。“打开”阶段(在“从”阶段之后)然后修剪VT1并生成VT2(小得多)。我只是好奇VT1阶段如何能便宜地工作?@Marty:如果不提供你所阅读内容的参考,你的问题可能会有一些解释。我指的是执行的查询,因为我就是这样解释你的问题的。请参阅Remus的答案以获得解释。对此表示抱歉:感谢您的评论!笛卡尔连接(据我所知)在执行查询时发生在“幕后”(即使使用“ON”子句)。这发生在查询处理的“FROM”阶段。“打开”阶段(在“从”阶段之后)然后修剪VT1并生成VT2(小得多)。我只是好奇VT1阶段如何能便宜地工作?@Marty:如果不提供你所阅读内容的参考,你的问题可能会有一些解释。我指的是执行的查询,因为我就是这样解释你的问题的。请参阅Remus的答案以获得解释。对此表示抱歉:感谢您的评论+1:这是一个很好的观点。在我的回答中,我