Oracle:查询优化

Posted

技术标签:

【中文标题】Oracle:查询优化【英文标题】:Oracle:query optimization 【发布时间】:2015-10-27 09:38:46 【问题描述】:

我有两个表 tab1tab2.tab1 有 108000 行,tab2 有 1200000 行。 这是示例数据tab1

+-----------------------------------------------------+
|       Low        |         high        | Region_id  |
+-----------------------------------------------------+
|5544220000000000  |   5544225599999999  |     1      |
|5544225500000000  |   5544229999999999  |     2      |
|5511111100000000  |   5511111199999999  |     3      |
+-----------------------------------------------------+    

tab2

+------------------+
|       pan        |
+-------------------
|5544221111111111  |
|5544225524511244  |
|5511111111254577  |
+------------------+ 

所以我运行这样的查询

select t2.pan, t1.region_id from tab2 t2
 join tab1 t1 on t2.pan between t1.low and t1.high;

我要做的是找出tab2.pan 存在于哪个范围内并检索它是region_id:范围是唯一的,这意味着低对和高对是不同的。 我尝试添加索引,并行运行,但查询运行速度非常慢(大约 3 小时)。 任何人都可以建议一些东西来加快查询,它可以添加某种索引,或者更改数据结构或其他任何东西。 我正在针对 Oracle 11gR2 运行查询。 更新 从 cmets 我测试了几件事 添加像(高,低)这样的索引并添加索引(泛)和(高,低,区域),两种方式都有索引全扫描,我也尝试了索引(低,高)和泛索引,这样索引tab1 上的范围扫描和 tab2 上的索引全扫描,但无论如何它似乎非常慢。

【问题讨论】:

索引、主键、外键? @jarlh 我已经尝试在 tab1.high 和 tab1.low 中添加索引,但是会进行索引全扫描并且查询工作非常缓慢。 tab1 和 tab2 都没有主键。 我认为关于(低,高)的多列索引。我认为这样引擎将在 tab1 上执行索引范围扫描。 大概除了您在表格中提到的那些列之外,还有其他列?假设这是真的,您是否尝试过在 (low, high, region) 的 T1 和 (pan) 的 T2 上建立索引? @NeriaNachum 我没试过,我马上试试 【参考方案1】:

如果您没有重叠并且tab1 中的每个值与tab2 中的一行完全匹配,那么我认为最好的方法是使用正确索引的相关子查询:

select t.*, t2.region_id
from (select t1.*,
             (select max(t2.low)
              from tab2 t2
              where t2.low <= t.pan
             ) as t2low
      from tab1 t1
     ) t join
     tab2 t2
     on t.t2low = t2.low;

您想要的索引是tab2(low, region)。该索引应该非常有效地用于子查询以获得最接近的low 值。连接也应该很快。

这对你的表现有帮助吗?

编辑:

我应该注意,在上面的查询中,您可以测试外连接中的high 值。如果low 值是唯一的,这应该没问题,因为low 上的连接会非常快。所以:

select t.*,
       (case when t.pan <= t2.high then t2.region_id end) as region_id
from (select t1.*,
             (select max(t2.low)
              from tab2 t2
              where t2.low <= t.pan
             ) as t2low
      from tab1 t1
     ) t join
     tab2 t2
     on t.t2low = t2.low;

【讨论】:

我会在测试结束后尽快回信。 先生,看来工作正常。一旦我在生产环境中尝试,我会立即接受这个答案,不幸的是,今天不可能。

以上是关于Oracle:查询优化的主要内容,如果未能解决你的问题,请参考以下文章

Oracle大量数据查询优化

oracle怎么优化

oracle查询的查询优化

oracle查询优化之子查询条件优化

求助oracle like%.%模糊查询优化

Oracle - 查询优化 - 查询运行时间长