我有一个表(50 M行),它在column_a和column_b上有索引
当我做select count(*) from table where column_a in (list_a)
时,我很快就得到了结果。
与select count(*) from table where column_b in (list_b)
相同。
但当我这样做select count(*) from table where column_a in (list_a) or column_b in (list_b)
我的查询变得非常慢,在输出正确的数字之前要持续半个小时...我做错了什么吗?我该如何优化这个查询的实际行为?
谢谢你!
计划查询1:
Plan hash value: 2471097773
-------------------------------------------------------------
| Id | Operation | Name |
-------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT AGGREGATE | |
| 2 | NESTED LOOPS | |
| 3 | SORT UNIQUE | |
| 4 | TABLE ACCESS FULL | LIST_A |
| 5 | BITMAP CONVERSION COUNT | |
| 6 | BITMAP INDEX SINGLE VALUE| MY_TABLE_IX02 |
-------------------------------------------------------------
查询2的计划
Plan hash value: 1870911518
-------------------------------------------------------------
| Id | Operation | Name |
-------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT AGGREGATE | |
| 2 | NESTED LOOPS | |
| 3 | SORT UNIQUE | |
| 4 | TABLE ACCESS FULL | LIST_B |
| 5 | BITMAP CONVERSION COUNT | |
| 6 | BITMAP INDEX SINGLE VALUE| MY_TABLE_IX05 |
-------------------------------------------------------------
计划查询3:
Plan hash value: 1821967683
----------------------------------------------------------------
| Id | Operation | Name |
----------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT AGGREGATE | |
| 2 | FILTER | |
| 3 | VIEW | index$_join$_001 |
| 4 | HASH JOIN | |
| 5 | BITMAP CONVERSION TO ROWIDS| |
| 6 | BITMAP INDEX FULL SCAN | MY_TABLE_IX02 |
| 7 | BITMAP CONVERSION TO ROWIDS| |
| 8 | BITMAP INDEX FULL SCAN | MY_TABLE_IX05 |
| 9 | TABLE ACCESS FULL | LIST_A |
| 10 | TABLE ACCESS FULL | LIST_B |
----------------------------------------------------------------
2条答案
按热度按时间rxztt3cl1#
根据我的经验,OR往往会对查询产生负面影响(比如忽略索引和触发全表扫描)。有时候这并不是很糟糕,但我遇到过这样的查询,它从 lightning 般的速度变成了几分钟。
一个可能的解决方案是将
OR
更改为UNION
甚至UNION ALL
。我过去曾成功地使用此方法来提高查询的性能,但您将不得不将它们相互比较,以确定此方法是否适用于您。您可以尝试以下三个选项,看看其中任何一个选项是否比其他选项有显著改进。
原始查询(已编辑为返回行,因为您提到返回数据而不是进行计数):
避免
OR
:由于
UNION
会触发DISTINCT
,因此也值得尝试一下:yqyhoc1h2#
我 猜 Oracle 在 前 两 个 查询 中 使用 索引 , 而 在 第 三 个 查询 中 进行 全 表 扫描 。 如果 您 仔细 考虑 一下 , Oracle 不能 在 第 三 个 查询 中 使用 索引 的 原因 是 合乎 逻辑 的 :
但是 , 这 两 个 索引 都 不会 向 Oracle 提供 有关 ( column _ a , column _ b ) 组合 的 信息 。 因此 , 为了 加快 查询 速度 , 您 需要 一 个 同时 包含 column _ a 和 column _ b 的 索引 。