附件是fiddle,它在每个表的旁边放置我的模式,并在每个表中指示行数。查询看起来像是这样,以防小提琴被阻止:
select distinct cat_name,cat_age, co_cat_owners_id,cat_weight,cs_is_alive,os_is_current, cos_is_current,
sum(cat_age) over(partition by co_cat_owners_id) running_total
from
(
select co.cat_owners_id co_cat_owners_id,
co.cat_id co_cat_id,
co.owner_id co_owner_id,
co.vet_id co_vet_id,
cos.is_current cos_is_current,
os.is_current os_is_current,
cs.is_alive cs_is_alive,
cat.name cat_name,
cat.age cat_age,
cat.weight cat_weight
from cat_owners co,
cat_owner_statuses cos,
cat_statuses cs,
cats cat,
owners o,
owner_statuses os
where o.owner_id = co.owner_id
and cat.cat_id = co.cat_id
and cos.last_visit >= sysdate - 4/24
)
where cs_is_alive = '1'
and (cos_is_current = '1' OR os_is_current='1')
group by cat_name,cat_age,cat_weight,cs_is_alive,os_is_current,co_cat_owners_id,cos_is_current;
在我的开发环境中,解释计划在步骤方面非常接近于小提琴中的内容,但是我确实有几个步骤,其中内存大小为15E(exabytes),行数为4000P(petabytes)。我的问题是,在创建索引/错误SQL的过程中,我设法为一个问题生成15 exabyte解决方案,这个问题应该可以在更少的空间和时间内解决。我注意到调整一些复合索引创建步骤会产生稍微不同的结果,但我仍然被Exabyte空间要求阻止。
注意
如果将来某人没有阅读所有评论,则运行以下函数并结合正确的联接有助于:
analyze table table_name_here compute statistics;
答案 0 :(得分:3)
您的查询在FROM
子句中有6个表,但您只指定了两个连接条件。 OWNERS
有1000万行,CAT_OWNERS
有1.2亿行,所以我猜这个连接产生了1.2亿行。然后你加入到有{100}行的CATS
,所以我假设你已经拥有了1.2亿行。但是,从那里,你没有更多的加入条件。因此,您的1.2亿行中间结果得到了笛卡尔与5亿行CAT_OWNER_STATUSES
表的连接,该表生成1.2亿* 5亿行,即60万亿行。笛卡尔将其连接到1000万行CAT_STATUSES
表,最终得到60万亿* 1000万行,现在我们达到了6 * 10 ^ 23行。然后你笛卡尔再次加入OWNER_STATUSES
,它有9000万行,给你5.4 * 10 ^ 31行。如果您需要合理数量的结果,则需要指定其他连接条件以避免使用笛卡尔积。
遗憾的是,在您的小提琴中遵循数据模型有点困难,因为似乎有许多可能相互矛盾的方式将表连接在一起。 CAT_VETS
将猫映射到兽医,但CAT_OWNERS
也是如此。select distinct cat_name,cat_age, co_cat_owners_id,cat_weight,cs_is_alive,os_is_current, cos_is_current,
sum(cat_age) over(partition by co_cat_owners_id) running_total
from
(
select co.cat_owners_id co_cat_owners_id,
co.cat_id co_cat_id,
co.owner_id co_owner_id,
co.vet_id co_vet_id,
cos.is_current cos_is_current,
os.is_current os_is_current,
cs.is_alive cs_is_alive,
cat.name cat_name,
cat.age cat_age,
cat.weight cat_weight
from cat_owners co,
cat_owner_statuses cos,
cat_statuses cs,
cats cat,
owners o,
owner_statuses os,
cat_vets cv,
owner_vets ov
where o.owner_id = co.owner_id
and cat.cat_id = co.cat_id
and cos.cat_owners_id = co.cat_owners_id
and cs.cat_vets_id = cv.cat_vets_id
and os.owner_vets_id = ov.owner_vets_id
and ov.owner_id = o.owner_id
and co.vet_id = ov.vet_id
and co.vet_id = cv.vet_id
and cos.last_visit >= sysdate - 4/24
)
where cs_is_alive = '1'
and (cos_is_current = '1' OR os_is_current='1')
group by cat_name,cat_age,cat_weight,cs_is_alive,os_is_current,co_cat_owners_id,cos_is_current;
如果没有数据和预期结果,就很难猜测表格应该如何连接。我的猜测是你需要像this modified fiddle
{{1}}
答案 1 :(得分:2)
由于您未使用连接语法,因此错过了将cat_statuses,cat_owner_statuses和owner_statuses的任何行与任何其余表连接在一起。这将导致每个表和连接表之间的交叉连接。这两个'状态'表包含多少行?
考虑加入每个表而不是用逗号列出它们,然后使用where过滤掉。我不确定SQL如何处理逗号分隔表(也可能是交叉连接) ...
from owners o,
join cat_owners co on o.owner_id = co.owner_id
join cats cat on cat.cat_id = co.cat_id
join cat_owner_statuses cos on XXXXX
join cat_statuses cs on XXXXX,
join owner_statuses os on XXXXX
where cos.last_visit >= sysdate - 4/24
答案 2 :(得分:0)
您的几个表(例如cat_statuses
)之间没有关系,因此产品联接会返回数以万计的行。也许您需要在您的小提琴示例中加入名为cat_vets
的表格。
至少,您应该将外部where
条件移动到派生表查询中;把它放在外面是没有效率的。