Oracle SQL 子查询与内连接

Oracle SQL sub query vs inner join

起初,我在Oracle Docs上看到了select的说法。

当我的查询包含 select、join、where 时,我对 oracle select 的行为有一些疑问。

请参阅下面的信息:

My sample table:

[ P_IMAGE_ID ]
 IMAGE_ID (PK)
 FILE_NAME
 FILE_TYPE
 ...
 ...

[ P_IMG_TAG ]
 IMG_TAG_ID (PK)
 IMAGE_ID (FK)
 TAG
 ...
 ...

我的要求是:区分标签为“70702”的图像。


方法 1:Select -> 加入 -> 位置 -> 区分

SELECT DISTINCT PID.IMAGE_ID
              , PID.FILE_NAME
FROM P_IMAGE_ID PID
INNER JOIN P_IMG_TAG PTAG
        ON PTAG.IMAGE_ID = PID.IMAGE_ID
WHERE PTAG.TAG = '70702';

我认为查询行为应该是这样的:

join table -> hint where cause -> distinct select

我使用 Oracle SQL 开发人员来获取解释计划:

方法 1 成本 76.


方法 2:Select -> 哪里 -> 哪里 -> 不同

SELECT DISTINCT PID.IMAGE_ID
              , PID.FILE_NAME
FROM P_IMAGE_ID PID
WHERE PID.IMAGE_ID IN 
(
  SELECT PTAG.IMAGE_ID
  FROM P_IMG_TAG PTAG
  WHERE PTAG.TAG = '70702'
);

我认为第二个查询行为应该是这样的:

hint where cause -> hint where cause -> distinct select

我也使用 Oracle SQL 开发人员来获取解释计划:

方法 2 也花费了 76。为什么?

我相信当我首先尝试 where cause 以减少数据库进程并避免连接 table 时,查询性能应该比 table 连接查询更好,但现在当我测试它时,我很困惑,为什么 2 种方法成本相等? 还是我误解了什么?

我的问题列表在这里:

  1. 为什么以上2种方法成本相等?

  2. 如果sub select Tag = '70702'的结果超过千或百万以上,用join table应该更好吧?

  3. 如果subselectTag = '70702'的结果最少,用subselect减少数据查询过程比较好吧?

  4. 当我使用方法 1 时 Select -> Join -> Where -> Distinct 表示数据库进程 table 在提示之前加入,原因是什么?

  5. 当我将 hint cause Tag = '70702' 移动到 join cause 时有人告诉我 (即 INNER JOIN P_IMG_TAG PTAG ON PAT.IMAGE_ID = PID.IMAGE_ID AND PTAG.TAG = '70702' )它的性能可能更好,没关系?

我阅读了主题 subselect vs outer join and subquery or inner join,但两者都是针对 SQL 服务器的,我不确定是否像 Oracle 数据库。

DBMS 获取您的查询并执行某事。但它不会按照 SQL 语句中出现的顺序执行与 SQL 语句部分相对应的步骤。

了解 "relational query optimization", which could just as well be called "relational query implementation". Eg for Oracle

任何语言处理器都将声明和调用作为输入,并根据内部数据结构和操作来实现所描述的行为,可能通过 "intermediate code" 运行 [=32] 上的一个或多个级别=],最终归结为物理机。但即使只是保持输入语言,SQL 查询也可以重新排列成其他SQL 查询 return 相同的值,但在简单和一般的实施假设下表现 显着更好 。正如您知道您的问题的查询对于给定的数据库总是 return 一样,DBMS 可以知道。它知道的部分原因是有很多规则可以获取关系代数表达式并生成不同但相同值的表达式。某些重写规则适用于某些有限的情况。有些规则会考虑 SQL 级别的关系事物,例如主键、唯一列、外键和其他约束。其他规则使用面向实现的 SQL 级别的东西,例如索引和统计信息。这是关系查询优化的 "relational query rewriting" 部分。

即使两个不同但等效的查询生成不同的计划,成本也可能相似,因为计划非常相似。在这里,哈希和排序索引都是唯一的。 (如果知道每个查询的 少数 个顶级计划是什么会很有趣。很可能这几个计划对两者都是相同的,但更直接的计划派生自特定输入表达式的是在差异不大时提供的表达式。)

让 DBMS 找到好的查询计划的方法是编写您能找到的最自然的查询表达式。