2009-10-21 72 views
1

我有以下查询从交易表和交易明细获取交易。这两个表都有大量条目,所以此查询需要一段时间才能返回结果。避免全表扫描

SELECT * FROM transactions t LEFT JOIN transac_detail tidts ON (tidts.id_transac = t.id); 

不过,我因为事实上,甲骨文执行全表扫描两个表,根据解释计划,即使t.id和tidts.id_transac有索引,更担心。

有什么办法可以在不触及表结构的情况下优化它吗?

+0

Oracle做什么?散列连接?哈希联接非常快,通常比使用索引的执行计划更快。向我们展示您的解释计划并检查统计数据是否准确。 – tuinstoel 2009-10-21 18:48:43

回答

4

我不认为这是真的,SQL必须最好与全表扫描服务。在两者之间存在外键的情况下,这确实是最明显的事实,但即使如此,也可能有例外。

我认为关键的问题是这样的:“每个表中的行的比例应该包含在结果集中?”。如果答案是“100%来自每个”,那么你就有了全表扫描(和散列连接)的清晰情况。

但是考虑一下情况,即表A和表B连接在一起,表A包含5行,并且包含100行的表B(父)的外键包含一行。很明显,在这里你需要用B的嵌套循环连接来查找A的完整扫描(表B中的连接列将被索引,因为它必须是主键或唯一键)。

在OP的情况下,虽然看起来你会期望从每个表中返回100%的行。我期望看到对这两个表的完整扫描,并且首先访问带有TRANSACTIONS(可能是较小的表)的散列连接并将其构建到散列表中。这将是最佳的连接方法,我只是在寻找一种情况,即单次散列连接的TRANSACTIONS太大。如果连接溢出到磁盘上,那么这可能是一个性能问题,您必须考虑增加内存分配或等分两个表以减少内存需求。

+0

非常全面的答案,一如既往。 +1 – 2009-10-21 16:32:21

0

全表扫描不一定是坏的 - 它似乎并不是以任何方式限制结果集,这可能是执行查询的最有效方式。您始终可以通过使用索引提示并确定结果的性能更改来验证此情况。

2

由于给定的查询返回所有内容,全表扫描实际上可能是达到最终结果的最快方式。由于I/O与CPU时间相比非常昂贵,因此将所有内容拉入内存并进行最终连接可能更有效,而不是在一个表中循环查找索引。

要确定查询是否可能实际上跑得更快,你可以试试下面的方法:

  • 看看查询计划仅在数据的子集(例如,一系列的id的)
  • 尝试查询上大小不等的子集,看到你在这里密谋什么样的曲线
0

您没有一个WHERE子句,因此甲骨文认为,因为它必须从两个表返回所有记录全表扫描将是最有效的。

如果您要添加一个使用索引的WHERE子句,我想您会发现EXPLAIN PLAN将不再使用全表扫描。