2016-09-30 6 views
0

У меня есть сценарий, где мне нужно искать & отображать записи из огромных столов с большим количеством строк. У меня есть предопределенные критерии поиска для моих таблиц, для которых пользователь может предоставить фильтр &.Принудительное использование первичного ключа в Oracle во время поиска

Учитывая образец таблицы:

CREATE TABLE suppliers 
(supplier_name varchar2(50) NOT NULL, 
    address varchar2(50), 
    city varchar2(50) NOT NULL, 
    state varchar2(25), 
    zip_code varchar2(10), 
    CONSTRAINT "suppliers_pk" PRIMARY KEY (supplier_name, city) 
); 


INSERT INTO suppliers VALUES ('ABCD','XXXX','YYYY','ZZZZ','95012'); 
INSERT INTO suppliers VALUES ('EFGH','MMMM','NNNN','OOOO','95010'); 
INSERT INTO suppliers VALUES ('IJKL','EEEE','FFFF','GGGG','95009'); 

я предоставил пользователю поля поиска в качестве первичного ключа - Имя поставщика, город

Если он входит в оба поля, мое исполнение запроса будет хорошо, так как он идет для сканирования индекса

SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' and city = 'ZZZZ'; 

| Id | Operation     | Name   | Rows | Bytes | Cost (%CPU)| Time  | 
-------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT   |    |  1 | 102 |  1 (0)| 00:00:01 | 
| 1 | TABLE ACCESS BY INDEX ROWID| SUPPLIERS |  1 | 102 |  1 (0)| 00:00:01 | 
|* 2 | INDEX UNIQUE SCAN   | suppliers_pk |  1 |  |  1 (0)| 00:00:01 | 

Однако, если он входит только один из поля поиска, моя производительность запроса будет идти плохо, так как он идет за полный стол сканирование

SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' ; 

| Id | Operation   | Name  | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |   |  1 | 102 |  3 (0)| 00:00:01 | 
|* 1 | TABLE ACCESS FULL| SUPPLIERS |  1 | 102 |  3 (0)| 00:00:01 | 

Есть ли способ, чтобы заставить оракул думать, что это первичный ключ поиска, когда я не все ключевые поля в поиске, что-то вроде ниже (что, очевидно, не работает)

SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' and city = city; 

Спасибо.

+2

Oracle может сделать пропуск сканированием индексного поиском, если он считает, что это целесообразно и более эффективным, чем полное сканирование таблицы. Как правило, оптимизатор довольно хорош в выборе лучшего плана с доступными индексами, предполагая, что статистика обновлена. Если он думает, что он не может выполнить сканирование, возможно, вам нужен отдельный индекс в 'city'? Использование индекса PK вряд ли будет эффективным - вероятно, он будет выполнять полное сканирование индексов, а затем все же придется извлекать блоки данных для соответствующих строк. –

+3

У вас всего 3 строки в таблице. Добавьте 10 000 строк, соберите статистику и проанализируйте результаты. –

+0

Спасибо, я попробовал на стол с миллионами строк, вместо FTS вместо него использовался INDEX RANGE SCAN. – ppatkar

ответ

0

Вы думаете об этом не так.

Оптимизатор запросов выбирает то, что он считает лучшим планом выполнения запроса на основе информации, доступной на момент анализа запроса (или иногда при изменении параметров). Как правило, если вы дадите ему правильную информацию с точки зрения статистики и т. Д., Она обычно будет делать хорошую работу.

Возможно, вы думаете, что знаете это лучше, но помните, что вы не будете контролировать это для жизни базы данных. Данные изменяются, вы хотите, чтобы база данных могла реагировать и изменять план выполнения, когда это необходимо.

Тем не менее, если вы настроены на заставляя его использовать индекс, вы можете использовать подсказку:

SELECT /*+ INDEX(suppliers suppliers_pk) */ 
supplier_name, address, city, state, zip_code FROM suppliers where 
supplier_name = 'ABCD' ; 
0

Полное сканирование таблицы не обязательно плохое. У вас всего несколько строк в таблице, поэтому оптимизатор считает, что лучше делать FTS, чем сканирование диапазона индексов. Он начнет использовать индекс PK, как только RDBMS подумает, что это лучше, т. Е. У вас много строк, а ограничение на определенном поставщике значительно снижает результат. Если вы хотите искать только город, а не поставщик, вам нужен еще один индекс только с городом (или, по крайней мере, начиная с города). Имейте в виду, что вам, возможно, придется обновлять статистику таблицы после того, как вы загрузили таблицу большими объемами данных. Всегда важно проверить производительность запросов с каким-то реалистичным количеством данных.

0

Индекс сначала организован на имя поставщика_определения по городу, поэтому использовать этот индекс для запроса невозможно только по городу. Пожалуйста, создайте второй индекс, основанный только на городе. Это поможет вашему запросу.

+0

[Это необязательно верно] (https://docs.oracle.com/cd/E11882_01/server.112/e40540/indexiot.htm#CHDHGIHA). Хотя в этом случае оптимизатор считает, что сканирование пропусков будет неэффективным, по-видимому, потому, что есть много поставщиков, поэтому он недостаточно избирателен для такого подхода. –