1

附件是一个小提琴,它在每个表旁边用注释来布置我的模式,以指示上述每个表中的行数。查询看起来像这样,以防小提琴被阻塞:

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(EB),行数为 4000P(PB)。我的问题是,在创建索引/错误 SQL 的过程中,我是否设法生成了一个 15 EB 的解决方案来解决应该可以在更少的空间和时间内解决的问题。我注意到调整一些复合索引创建步骤会产生稍微不同的结果,但我仍然被 Exabyte 空间要求所阻止。

笔记

如果将来有人没有阅读所有评论,请结合正确的连接运行以下功能:

analyze table table_name_here compute statistics;
4

3 回答 3

3

您的查询在子句中有 6 个表,FROM但您只指定了两个连接条件。 OWNERS有 1000 万行,CAT_OWNERS有 1.2 亿行,所以我猜测连接会产生 1.2 亿行。然后你加入CATS其中有 100 万行,所以我假设此时你有 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;
于 2012-11-20T18:34:41.520 回答
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
于 2012-11-20T18:32:50.910 回答
0

您的几个表(例如cat_statuses)没有关系,因此产品连接返回数以亿计的行。也许您需要通过cat_vetsFiddle 示例中命名的表进行连接。

至少,您应该将外部where条件移动到派生表查询中;把它放在外面是低效的。

于 2012-11-20T18:33:00.497 回答