为什么两个数字的 UNION 比它们的总和更有效?
Why is a UNION on two numbers more efficient than their sum?
我们要确保一个位置(具有特定类型的库存)的调色板不超过 maxCount 个。
为了确保这一点,我们总结了其上带有调色板的位置或调色板将位于的位置。两种说法都可以正常工作。但是,我的初稿表现不佳。我的导师想出了一个不同的草稿,速度要快得多,但他无法解释原因。
慢语句:
AND maxCount > (
SELECT
trptoloc+atloc
FROM
(
SELECT
COUNT(DISTINCT loc2.locnam) AS atloc
FROM
loc_t loc2,
pal_t pal,
inv_t inv,
art_t art
WHERE
loc.group = loc2.group
AND pal.locnam = loc2.locnam
AND inv.palnam = pal.palnam
AND inv.artid = art.artid
AND AND art.feature = value
),
(
SELECT
COUNT(DISTINCT loc2.locnam) AS trptoloc
FROM
trp_t trp,
loc_t loc2,
inv_t inv,
art_t art
WHERE
trp.locnamezl = loc2.locnam
AND trp.palnam = inv.palnam
AND loc.group = loc2.group
AND inv.artid = art.artid
AND art.feature = value;
)
)
更快的语句:
AND maxCount > (
SELECT
SUM(invpal)
FROM
(SELECT
COUNT(distinct inv.palnam) AS invpal
FROM
inv_t inv,
art_t art,
pal_t pal,
loc_T loc2
WHERE
inv.artid = art.artid
AND loc.group = loc2.group
AND pal.locnam = loc2.locnam
AND inv.palnam = pal.palnam
AND art.feature = value;
UNION ALL
SELECT COUNT(distinct inv.palnam) AS invpal
FROM
inv_t inv,
art_t art,
trp_t trp,
loc_T loc2
WHERE
trp.locnamezl = loc2.locnam
AND trp.palnam = inv.palnam
AND loc.group = loc2.group
AND inv.artid = art.artid
AND art.feature = value;
)
)
任何有助于我理解性能差异的提示或 link 都非常感谢!
您的第一个示例是加入两个内联视图。这不一定是坏事,但如果你看一下解释计划,Oracle 可能正在对这两个视图进行嵌套循环,这意味着它将它们分别加载到内存中,然后将它们连接在一起(什么都没有 - 这是一个 cross/cartesian加入)。
在 UNION ALL 示例中,优化器不必执行任何复杂的操作 - 它只运行前半部分,然后运行后半部分,然后对两行求和。它不会尝试将两个查询同时保存在内存中,以便将它们相互比较。
作为旁注,there are often ways to rewrite inline views to perform better,尽管它会使您的代码更难理解。你没有给我们很多关于你的 table 结构或数据的细节,但我认为你可以重写这个查询,这样它只读取每个 table 一次而不是两次,例如
AND maxCount > (
select count(distinct inv.palnam)
from inv_t inv
join art_t art
on inv.artid = art.artid and art.feature = value
join loc_T loc2
on loc.group = loc2.group
left join pal_t pal
on pal.locnam = loc2.locnam
and pal.palnam = inv.palnam
left join trp_t trp
on trp.palnam = inv.palnam
and trp.locnamezl = loc2.locnam
where pal.palnam is not null or trp.palnam is not null
)
我还重写了它以使用显式 ANSI 连接,就像 Gordon 所建议的那样。
我们要确保一个位置(具有特定类型的库存)的调色板不超过 maxCount 个。 为了确保这一点,我们总结了其上带有调色板的位置或调色板将位于的位置。两种说法都可以正常工作。但是,我的初稿表现不佳。我的导师想出了一个不同的草稿,速度要快得多,但他无法解释原因。
慢语句:
AND maxCount > (
SELECT
trptoloc+atloc
FROM
(
SELECT
COUNT(DISTINCT loc2.locnam) AS atloc
FROM
loc_t loc2,
pal_t pal,
inv_t inv,
art_t art
WHERE
loc.group = loc2.group
AND pal.locnam = loc2.locnam
AND inv.palnam = pal.palnam
AND inv.artid = art.artid
AND AND art.feature = value
),
(
SELECT
COUNT(DISTINCT loc2.locnam) AS trptoloc
FROM
trp_t trp,
loc_t loc2,
inv_t inv,
art_t art
WHERE
trp.locnamezl = loc2.locnam
AND trp.palnam = inv.palnam
AND loc.group = loc2.group
AND inv.artid = art.artid
AND art.feature = value;
)
)
更快的语句:
AND maxCount > (
SELECT
SUM(invpal)
FROM
(SELECT
COUNT(distinct inv.palnam) AS invpal
FROM
inv_t inv,
art_t art,
pal_t pal,
loc_T loc2
WHERE
inv.artid = art.artid
AND loc.group = loc2.group
AND pal.locnam = loc2.locnam
AND inv.palnam = pal.palnam
AND art.feature = value;
UNION ALL
SELECT COUNT(distinct inv.palnam) AS invpal
FROM
inv_t inv,
art_t art,
trp_t trp,
loc_T loc2
WHERE
trp.locnamezl = loc2.locnam
AND trp.palnam = inv.palnam
AND loc.group = loc2.group
AND inv.artid = art.artid
AND art.feature = value;
)
)
任何有助于我理解性能差异的提示或 link 都非常感谢!
您的第一个示例是加入两个内联视图。这不一定是坏事,但如果你看一下解释计划,Oracle 可能正在对这两个视图进行嵌套循环,这意味着它将它们分别加载到内存中,然后将它们连接在一起(什么都没有 - 这是一个 cross/cartesian加入)。
在 UNION ALL 示例中,优化器不必执行任何复杂的操作 - 它只运行前半部分,然后运行后半部分,然后对两行求和。它不会尝试将两个查询同时保存在内存中,以便将它们相互比较。
作为旁注,there are often ways to rewrite inline views to perform better,尽管它会使您的代码更难理解。你没有给我们很多关于你的 table 结构或数据的细节,但我认为你可以重写这个查询,这样它只读取每个 table 一次而不是两次,例如
AND maxCount > (
select count(distinct inv.palnam)
from inv_t inv
join art_t art
on inv.artid = art.artid and art.feature = value
join loc_T loc2
on loc.group = loc2.group
left join pal_t pal
on pal.locnam = loc2.locnam
and pal.palnam = inv.palnam
left join trp_t trp
on trp.palnam = inv.palnam
and trp.locnamezl = loc2.locnam
where pal.palnam is not null or trp.palnam is not null
)
我还重写了它以使用显式 ANSI 连接,就像 Gordon 所建议的那样。