Oracle:查询优化
Posted
技术标签:
【中文标题】Oracle:查询优化【英文标题】:Oracle:query optimization 【发布时间】:2015-10-27 09:38:46 【问题描述】:我有两个表 tab1
和 tab2
.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:查询优化的主要内容,如果未能解决你的问题,请参考以下文章