创建高效的Oracle / PL SQL分组和时间查询

时间:2011-09-16 17:56:05

标签: database oracle

我再次需要数据库帮助。是效率很重要。

我有一张桌子

让我们说。 其中ID是主键。

Id Activity Time 
1. Lunch     2:00
2. Lunch     1:00
4. Lunch     4:00
5. Meeting   1:00
6. Meeting   12:00
7. Meeting   3:00
8. break     1:00

我希望查询返回。

每次活动都是最近一次。

所以答案就是。

4. Lunch   4:00
7. Meeting 3:00
8. break   1:00

我用完了 嵌套选择我将返回整个表的位置,然后选择

first_value(table) over (partition by activity order by time desc)

但我正在寻找一种更有效的方法来做到这一点

谢谢。

select activity, max(time) from mytable group by activity

可以完美地工作,但它也会占用检索数据所需的时间,有没有什么方法可以更快?

3 个答案:

答案 0 :(得分:2)

重写简单的查询以使它们更快几乎不是答案。您想问的问题是“我可以对数据库进行哪些其他更改以使此查询更快。”

正如其他人所建议的那样,您始终可以创建物化视图。但是,由于这是一个聚合,您将无法快速刷新它。这意味着您可能必须决定是否允许结果定期不同步。

另一种可能性是在ID,活动和时间上添加索引,这将有效地对数据进行预排序,允许优化器在组之间跳转,而不是扫描每一行。


评论回复:您可以使用create index ak_activities_id_activ_time (id, activity, time);等语法创建索引。要理解为什么这会有所帮助,您需要首先了解一些数据库基础知识。

数据库存储表数据而根本没有任何组织。如果在表中查询特定值,则必须查看表中的每一行以查看它是否包含该值。聚合查询必须做更多工作:它必须将数据分组,然后将聚合函数应用于相应的列以找到您要查找的答案。

索引通过在幕后创建一个类似于表的对象来改进这一点,它保留了指定列中每个唯一值的有序集,以及找到值的行的地址。一旦有了索引,可以在索引中查找该列中的值,而无需查看每一行。由于值是有序的,因此数据库可以使用搜索逻辑而不是查看每个值。

如果索引中有多个列,则会创建一个值树。列出的第一列中的每个值仅在索引中找到一次。对于与其配对的第一列中的每个值,第二列中的每个值都会出现一次。此列表将继续列出您列出的列数。

这有助于您执行聚合时,因为它不需要排序和分组:这已经由索引完成了。当您查找最小值或最大值时,它可以进一步提供帮助,因为根据定义,它是索引的该分支中的第一个或最后一个条目。请注意,只有在索引中存在所有分组列时才会出现这种情况。

那么,你为什么不索引一切?答案是指数是一种权衡。设计良好的索引将加速某些查询,但每个索引都会占用磁盘空间并减慢插入和更新(索引必须与表一起修改)。通常这不太重要,但在表上创建过多索引会导致明显的性能问题。


现在我已经解释了一些基本的数据库概念,我有一个建议:雇用一个知道他们在数据库上工作的人。调优数据库与编程完全不同,要求应用程序员完成这项工作通常是浪费时间和金钱。即使它只是一个可以解决特定问题的顾问,但拥有可以访问您的数据库并了解其背后的理论的人将比在黑暗中感受自己的方式更有效率。

答案 1 :(得分:1)

select activity, max(time) from mytable group by activity

答案 2 :(得分:1)

select max(id), activity, max(time) from yourTable group by activity

这就足够了你的桌子是如你所示组织的。但是,如果您的ID或时间不是连续的,它将会中断。