0

我正在尝试做一些查询优化;将 SQL 查询带入关系代数并对其进行优化。

我的数据库表架构如下:

Hills(MId, Mname, Long, Lat, Height, Rating,... )
Runners(HId, HName, Age, Skill,... )
Runs(MId, CId, Date, Duration)

Runners 和 Hills 中可能有很多列。

我的 SQL 查询是:

SELECT DISTINCT Runners.HName, Runners.Age
FROM Hills, Runners, Runs
WHERE Runners.HId = Runs.HId AND Runs.MID = Hills.MId AND Height > 1200

所以我可以从做开始:

π Name, Age(σ Height > 1200 (Hills × Runners × Runs))

或者类似的东西,然后用一个很好的连接选择来优化它,但我不知道从哪里开始

4

1 回答 1

3

您可以从使用 SQL 连接表示法开始:

SELECT DISTINCT P.HName, P.Age
  FROM Hills   AS H
  JOIN Runs    AS R ON H.MId = R.MId
  JOIN Runners AS P ON P.HId = R.HId
 WHERE H.Height > 1200

然后您可以观察到 WHERE 条件仅适用于 Hills,因此您可以下推搜索条件:

SELECT DISTINCT P.HName, P.Age
  FROM (SELECT MId FROM Hills WHERE Height > 1200) AS H
  JOIN Runs    AS R ON H.MId = R.MId
  JOIN Runners AS P ON P.HId = R.HId

这是一种标准优化——SQL 优化器会自动执行。事实上,可能不值得对显示的第一个查询进行大量重写,因为优化器可以处理它。我认为可能的另一个优化是将 DISTINCT 操作降低一个级别:

SELECT P.HName, P.Age
  FROM (SELECT DISTINCT R.HId
          FROM (SELECT MId FROM Hills WHERE Height > 1200) AS H
          JOIN Runs AS R ON H.MId = R.MId
       ) AS R1
  JOIN Runners AS P ON P.HId = R1.HId

这使中间结果集尽可能小:R1 包含一个 ID 值列表,这些人至少跑过一个 1200 米(或者那是 1200 英尺?)山,并且可以 1:1 加入细节在 Runners 表中。看看优化器是否能够为自己推断 DISTINCT 的下推会很有趣。

当然,在关系代数中,DISTINCT 操作是“自动”完成的——每个结果和中间结果总是一个没有重复的关系。


给定原始的“关系代数”符号:

  • π 姓名, 年龄(σ 身高 > 1200 (Hills × Runners × Runs))

这对应于上面的第一条 SQL 语句。

然后,第二条 SQL 语句(或多或少)对应于:

  • π 姓名、年龄 ((π MId (σ 高度 > 1200 (Hills))) × Runners × Runs)

然后,第三条 SQL 语句(或多或少)对应于:

  • π 姓名、年龄 ((π HId ((π MId (σ 高度 > 1200 (Hills))) × Runs)) × Runners)

我假设括号强制关系代数按顺序计算表达式。我不确定我是否有尽可能少的括号,但那些括号并​​没有留下太多的模糊空间。

于 2010-11-27T20:29:00.997 回答