我正在尝试进行一些查询优化;将SQL查询带入关系代数并进行优化。
我的数据库表模式如下:
Hills(MId, Mname, Long, Lat, Height, Rating,... )
Runners(HId, HName, Age, Skill,... )
Runs(MId, CId, Date, Duration)
Runners and 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))
或类似的东西,然后用一个很好的连接选择来优化它,但我不知道从哪里开始
答案 0 :(得分: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包含运行至少一个1200米(或1200英尺?)小山的人的ID值列表,并且可以1:1连接使用Runners表中的详细信息。看看优化器是否能够推断出DISTINCT的下推是很有趣的。
当然,在关系代数中,DISTINCT操作是“自动”完成的 - 每个结果和中间结果总是一个没有重复的关系。
鉴于原始的“关系代数”符号:
这对应于上面的第一个SQL语句。
然后,第二个SQL语句(或多或少)对应于:
然后,第三个SQL语句(或多或少)对应于:
我假设括号强制关系代数按顺序计算表达式。我不确定那里是否有尽可能少的括号,但那里的括号并没有留下太大的暧昧空间。