我有一张表(5000万行),在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 |
-------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
计划查询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 |
-------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
计划查询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 |
----------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
以我的经验,OR倾向于对查询产生负面影响(例如忽略索引和触发全表扫描)。有时候情况还算不错,但是由于这个原因,我的查询从快速减少到花费几分钟。
一种可能的解决方案是将更改为,甚至更改OR为。过去,我在提高查询性能方面已经取得了成功,但是您必须将它们进行相互比较,以了解这是否对您有用。UNIONUNION ALL
您可以尝试以下三个选项,看看它们中的任何一个是否都比其他选项有了显着改进。
原始查询(已修改为返回行,因为您提到返回数据而不是进行计数):
select * from table where column_a in (list_a) or column_b in (list_b)
Run Code Online (Sandbox Code Playgroud)
查询避免OR:
select * from table where column_a in (list_a)
UNION
select * from table where column_b in (list_b)
Run Code Online (Sandbox Code Playgroud)
而且由于UNION触发了DISTINCT,这也值得尝试:
select * from table where column_a in (list_a) and not column_b in (list_b)
UNION ALL
select * from table where column_b in (list_b) and not column_a in (list_a)
UNION ALL
select * from table where column_a in (list_a) and column_b in (list_b)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3710 次 |
| 最近记录: |