Это всего лишь предположение, но хорошее (я думаю) и слишком длинное для комментария.
Я подозреваю, что произошла какая-то проблема преобразования набора символов, из-за которой база данных Oracleинтерпретировать значение привязки как NVARCHAR2
.Результирующее неявное преобразование типов затем не позволяет Oracle использовать ваш индекс.
Вот краткий пример того, что я имею в виду:
Настройка
CREATE TABLE matt1 ( a varchar2(30) );
INSERT INTO matt1 SELECT dbms_random.string('X',20) FROM dual CONNECT BY ROWNUM <= 50000;
COMMIT;
CREATE INDEX matt1_n1 ON matt1 (a);
Получитьпример значения
SELECT * FROM matt1 order by dbms_random.value fetch first 1 row only;
Я получил "UCBBTRAB0K8QV1UC8ERA" - вы получите другое значение, если вы попробуете это в своей собственной базе данных.
Имитируйте то, что вы делаете с помощью SQL * Developer:
EXPLAIN PLAN SET STATEMENT_ID='MM1' FOR
SELECT * FROM matt1 WHERE a = 'UCBBTRAB0K8QV1UC8ERA';
SELECT *
FROM TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE','MM1','ADVANCED'));
Plan hash value: 2474448389
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 1 (0)| 00:00:01|
|* 1 | INDEX RANGE SCAN| MATT1_N1 | 1 | 17 | 1 (0)| 00:00:01|
----------------------------------------------------------------------------
Пока все хорошо.Индекс используется.
Имитация того, что я думаю происходит через JDBC
EXPLAIN PLAN SET STATEMENT_ID='MM2' FOR SELECT * FROM matt1 WHERE a =
N'UCBBTRAB0K8QV1UC8ERA';
SELECT * FROM
TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE','MM2','ADVANCED'));
Plan hash value: 1348340248
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 51 | 50 (10)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| MATT1 | 3 | 51 | 50 (10)| 00:00:01 |
---------------------------------------------------------------------------
... lots of stuff omitted...
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(SYS_OP_C2C("A")=U'UCBBTRAB0K8QV1UC8ERA')
Вы можете видеть, что Oracleделая неявное преобразование типов в этом столбце базы данных.Эта функция преобразования типов не позволяет Oracle использовать индекс и приводит к полному сканированию таблицы.
Как вы можете проверить это
Чтобы подтвердить, действительно ли это ваша проблема, измените JDBC SQL навключить отличительный комментарий.Например,
String consultaSQL = "SELECT /* THIS_IS_MY_JDBC_STATEMENT_1 */ SE.ID_SAIDA_ESTOQUE, SE.DATA_ULTIMA_ATUALIZACAO, "
+ "SE.SITUACAO_VENDA, SE.ID_CLIENTE, SE.ID_ENTRADA_ESTOQUE_TROCA, SE.UUID, SE.ID_OPERACAO_MOVIMENTO, SE.ID_SETOR_ESTOQUE, SE.ID_EMPRESA, SE.ID_TERMINAL "
+ "FROM EST_SAIDA_ESTOQUE SE WHERE SE.UUID = ?"
Затем запустите программу JDBC и посмотрите в базе данных, чтобы узнать, что Oracle сделал с ней.Сначала найдите выполненный оператор в библиотечном кэше, например:
select sql_id, child_number from gv$sql where sql_text like
'%THIS_IS_MY_JDBC_STATEMENT_1%' and sql_text not like '%THIS_ONE%';
Затем используйте sql_id
и child_number
для просмотра плана.
SELECT *
FROM TABLE (DBMS_XPLAN.display_cursor ('gyzm0fq259h5d' /* sql_id */,
0 /* child_number */,
'ADVANCED LAST'));
ЕслиВ плане указывается полное сканирование таблицы, и в предикатной информации есть функция SYS_OP_C2C
(или аналогичная), тогда у вас есть объяснение.
Что вы можете с этим сделать
Самый простой способ, которымдолжно работать:
Измените свой JDBC SQL на этот:
String consultaSQL = "SELECT /* THIS_IS_MY_JDBC_STATEMENT_1 */ SE.ID_SAIDA_ESTOQUE, SE.DATA_ULTIMA_ATUALIZACAO, "
+ "SE.SITUACAO_VENDA, SE.ID_CLIENTE, SE.ID_ENTRADA_ESTOQUE_TROCA, SE.UUID, SE.ID_OPERACAO_MOVIMENTO, SE.ID_SETOR_ESTOQUE, SE.ID_EMPRESA, SE.ID_TERMINAL "
+ "FROM EST_SAIDA_ESTOQUE SE WHERE SE.UUID = CAST(? AS VARCHAR2(255 CHAR))"
(из OP: объясните план)
SqlDeveloper
JDBC ![Screenshot](https://i.stack.imgur.com/2LHeE.png)