1

我有两张桌子:

  • 行程:id_trip、id_object、trip_date、delta(8980026 行)
  • 范围:id_range、id_object、date_since、date_until(18490 行)

我需要优化下面的select语句

  select r.id_range, sum(t.delta) sum_deltas
    from trips t,
         ranges r
   where t.id_object = r.id_object
     and t.trip_date between r.date_since and r.date_until
group by r.id_range

根据条件,“范围”中的行程总是有一个匹配的行

  • trips 表不断增长,但没有更新或删除
  • 表范围可能会不时以任何方式更改(删除、更新、插入),因此基于函数的索引不是这种方式:(
  • id_object(在两个表中)和 date_since(在行程中)都有索引

有谁知道如何加快速度,甚至可能吗?

4

2 回答 2

1

您可能想查看您的数据分段(即按特定日期对数据进行分区,导致查询仅命中适当的分区)和索引,这些可能会加快查询过程。

此外,您可以考虑一个数据仓库......您说 Trips 永远不会被更新或删除,因此它是非规范化为更适合报告生成和临时查询的数据结构的理想候选者。

于 2012-06-06T08:59:14.603 回答
1

总是可以加快速度;它可能不值得花费时间/精力/金钱/磁盘空间/额外的开销等。

首先请使用显式连接语法。几十年来,它一直是 SQL 标准,它有助于避免许多潜在的错误。您的查询将变为:

select r.id_range, sum(t.delta) sum_deltas
  from trips t
  join ranges r
    on t.id_object = r.id_object
   and t.trip_date between r.date_since and r.date_until
 group by r.id_range

这个查询意味着你需要两个索引——如果可能的话是唯一的。在ranges你应该有一个关于id_object, date_since, date_until. 上的索引trips将是id_object, trip_date。如果trips更小,我可能会考虑添加delta到该索引的末尾,这样您就永远不会进入表,而只会进行索引扫描。就目前而言,您将不得不通过索引 rowid 进行表访问。

写完所有内容后,您的问题可能会略有不同。您将使用此查询对两个表进行全扫描。您的问题可能是索引。如果优化器正在使用索引,那么您可能正在对每个id_objectintripsranges然后进行索引唯一/范围扫描,因为使用了不在索引中的列,您将通过索引 rowid 进行表访问。这可能非常昂贵。

尝试添加提示以强制对两个表进行全扫描:

select /*+ full(t) full(r) */ r.id_range, sum(t.delta) sum_deltas
  from trips t
  join ranges r
    on t.id_object = r.id_object
   and t.trip_date between r.date_since and r.date_until
 group by r.id_range
于 2012-06-06T09:27:03.963 回答