4

考虑一个由多个表组成的视图...例如 a v_active_car,它由car连接到bodyengine和的表wheels组成stereo。它可能看起来像这样:

v_active_cars看法

SELECT * FROM car
    INNER JOIN body ON car.body = body.body_id
    INNER JOIN engine ON car.engine = engine.engine_id
    INNER JOIN wheels ON car.wheels = wheels.wheels_id
    INNER JOIN stereo ON car.stereo = stereo.stereo_id
    WHERE car.active = 1
    AND engine.active = 1
    AND wheels.active = 1
    AND stereo.active = 1

汽车的每个组件都有一个“活动”标志。现在,我需要找到现役汽车中可用的所有立体声音响。要做到这一点,需要使用整个视图,而不仅仅是stereo桌子——仅仅因为立体声音响处于活动状态并不意味着它可以在汽车中使用。

所以我可以

SELECT DISTINCT stereo_id FROM v_active_cars

尽管这可能会返回非常少量的行,但它仍然是一个非常慢的查询。

我试过这个,但它更慢:

SELECT stereo_id FROM stereo WHERE EXISTS
(SELECT 1 FROM v_active_cars WHERE stereo_id = stereo.stereo_id)

我还能做些什么来加快速度吗?

4

4 回答 4

1

你似乎做的一切都是正确的。下一步是检查索引覆盖率。

于 2009-02-10T17:04:08.647 回答
1
  1. 确保所有 JOIN 都有索引
    • 在您的情况下,每个级别都由一个键和一个标志选择。将标志添加为索引的一部分可能允许数据库仅使用索引,而不是读取整个记录
    • 确保您有足够的 RAM 来保存结果集。尤其是 InnoDB 表有很多你必须调整的旋钮。大多数默认设置假定硬件非常旧且 RAM 太少。
于 2009-02-10T17:23:17.837 回答
0

试试这个:

SELECT stereo_id
FROM stereo s, (
  SELECT *
  FROM v_active_cars
  ORDER BY stereo_id
  ) v
WHERE s.active = 1
  AND v.stereo = s.stereo_id

ORDER BY这里应该防止将谓词推入视图,优化器应该选择一个哈希连接。

于 2009-02-10T17:12:45.490 回答
0

您可以尝试为每个部分创建一个仅显示活动部分的视图,然后加入这些部分。例如。

VIEW activeCar
SELECT * FROM car WHERE car.active = 1

VIEW activeEngine
SELECT * FROM engine WHERE engine.active = 1

那么你的最终观点可以是

SELECT * FROM activeCar
INNER JOIN activeEngine ON activeCar.engine = activeEngine.engine_id

显然,请确保您在活动列上有一个索引。

另一种选择是在 id 和 active 标志上都有一个索引。然后,您可以在加入时执行 active=1。这样,只有一个索引用于加入,而不是一个用于 id 和一个用于活动。

SELECT * FROM car
INNER JOIN body ON car.body = body.body_id AND body.active = 1
INNER JOIN engine ON car.engine = engine.engine_id AND engine.active = 1
INNER JOIN wheels ON car.wheels = wheels.wheels_id AND wheels.active = 1
INNER JOIN stereo ON car.stereo = stereo.stereo_id AND stereo.active = 1
于 2009-02-10T17:14:18.857 回答