Остальные правы, вы не должны использовать числовой столбец, подобный этому.
Однако на самом деле именно конструкция OR <subquery>
вызывает проблему (производительности) в этом случае.Я не знаю, если это отличается в версии 11, но до версии 10gr2, это вызывает операцию фильтра с тем, что в основном является вложенным циклом с коррелированным подзапросом.В вашем случае использование числового столбца в качестве varchar также приводит к полному сканированию таблицы.
Вы можете переписать свой запрос следующим образом:
select *
from big
where id like '45%'
union all
select *
from big
join small using(id)
where id not like '45%';
В вашем тестовом примере яв итоге получим 174000 строк в большом и 9 маленьких.Выполнение вашего запроса занимает 7 секунд с 1211399 последовательных запросов.Выполнение моего запроса 0,7 секунды и использование 542 последовательных запросов.
Планы объяснения для моего запроса:
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)|
---------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8604 | 154 (6)|
| 1 | UNION-ALL | | | |
|* 2 | TABLE ACCESS FULL | BIG | 8603 | 151 (4)|
| 3 | NESTED LOOPS | | 1 | 3 (0)|
|* 4 | TABLE ACCESS FULL | SMALL | 1 | 3 (0)|
| 5 | TABLE ACCESS BY INDEX ROWID| BIG | 1 | 0 (0)|
|* 6 | INDEX UNIQUE SCAN | BIG_PK | 1 | 0 (0)|
---------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(TO_CHAR("ID") LIKE '45%')
4 - filter(TO_CHAR("SMALL"."ID") NOT LIKE '45%')
6 - access("BIG"."ID"="SMALL"."ID")
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
542 consistent gets
0 physical reads
0 redo size
33476 bytes sent via SQL*Net to client
753 bytes received via SQL*Net from client
76 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1120 rows processed