sql - 在任何数据库查询中总是有一个“基表”吗?
问题描述
好的,这只是理论上的,所以如果一个公正的数据库爱好者发表意见,那就太好了。
为了争论,让我们同意对于查询有“基表”这样的概念,其中一个表驱动结果集的大部分信息。想象一个查询,其中存在三个关系 - TableA、TableB 和 TableC
假设 TableA 有 100 万条记录,TableC 有 500 条记录,TableC 有 10,000 条记录。
假设查询是这样的 -
SELECT A.Col1
, A.Col2
, A.Col3
, A.Col4
, A.Col5
FROM TableA A
LEFT JOIN TableB B ON B.ID = A.TableBID
LEFT JOIN TableC C ON C.ID = A.TableCID
好的,显然TableA 是上面的基本关系。它是最大的表,它通过“从”连接来驱动结果集,从视觉上看,列甚至在结果集的“左侧”。(左边的东西实际上是我同事的标准)。
现在,假设 TableA 再次有 100 万行,TableB 是“连接”或“桥”表,有 500,000 行,TableC 有 1,000,000 行。因此,假设查询只是一个外连接,用于获取 TableA 和 TableC 中存在如下关系的所有列......
SELECT A.*
, C.*
FROM TableC C
FULL OUTER JOIN TableB B ON C.ID = B.TableAID
FULL OUTER JOIN TableA A ON A.ID = B.TableCID
好的,鉴于最后一个查询,谁能告诉我“基本关系”是什么?我不认为有一个,但希望另一个数据库人的意见。
解决方案
术语“基表”有一个定义,它与您所描述的无关。“基表”几乎只是一个“表”。也就是说,它不是视图,也不是表值函数,也不是查询的结果。它作为显式表存储在数据库中。
您似乎正在掌握的内容似乎与优化策略更相关。我在优化的上下文中使用了类似的术语来描述优化器正在访问的“驱动表”。这样做的目的是区分不同的执行计划。
考虑以下查询:
from t1 join t2 using (col)
有多种不同的执行计划。以下是一些方法以及可能被认为是它们的“驱动表”(如果有的话):
for each row in t1
for each row in t2
compare col
--> t1 is the "driving table"
for each row in t2
for each row in t1
compare col
--> t2 is the "driving table"
for each row in t1
look up t2 value using index on t2(col)
--> t1 is the "driving table"
sort t1 by col
sort t2 by col
compare the rows in the two sorted sets
--> no "driving table"
hash t1 by col
hash t2 by col
compare the hash maps
--> no "driving table"
换句话说,“驱动”表与查询结构关系不大。它基于用于查询的优化策略。也就是说,left join
s 和right join
s 限制了优化路径。因此,在嵌套循环或索引查找情况下,“第一个”(或“最后一个”)表将是驱动表。
推荐阅读
- c# - 使用 Selenium 和 C# 在 draggable=true 时拖放不工作
- java - 我这样做是为了让玩家面向鼠标方向,但因此出现了问题
- html - 如何避免下载文件重命名?
- java - 如何在 Spring Boot 的 @Query 注释中传递变量而不是表名?
- swift - 来自 url 的日期格式 (JSON)
- javascript - 如何使用 javascript 设置 ondragstart 属性
- c++ - 如何在 C++ 中为多个类类型指定相同的模板化成员函数?
- c# - SQLite VACUUM 命令更改 rowid 值
- angular - 我如何从一个返回对象数组的 Observable 创建一个对象
- c++ - C++二维指针数组初始化C2440