Oracle: индексирование подмножества строк таблицы - PullRequest
8 голосов
/ 05 октября 2011

У меня есть таблица, в которой есть активные и неактивные записи, active = 1 для активных и active = 0 для неактивных.

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

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

Есть ли способ в Oracle (10g) сделать что-то вроде этого:

create index an_idx on tab (active, col1, col2, ... , coln) where active = 1

Предыдущая попытка:

Я попытался использовать индекс на основе функции, чтобы установить для первого столбца значение NULL, когда active = 0 примерно так:

create index an_idx on tab (decode(active, 1, 1, null), col1, col2, ... , coln)

Но в этом случае Oracle по-прежнему индексирует неактивные столбцы.

Ответы [ 3 ]

12 голосов
/ 05 октября 2011

Ваша основная идея верна, но вам нужно применить декодирование ко всем столбцам. Только когда все индексированные выражения равны NULL, строка не будет проиндексирована.

create index an_idx on tab (
  decode(active, 1, col1, null),
  ...
  decode(active, 1, coln, null)
)

Конечно, если вы хотите, чтобы запрос использовал этот индекс, он должен использовать те же выражения в предложении WHERE.

Примечание. Не думаю, что вы хотите включить в индекс выражение decode(active, 1, 1, null), поскольку оно будет постоянным для всех проиндексированных строк.

8 голосов
/ 05 октября 2011

Разделите таблицу по ACTIVE, создайте локальные индексы и сделайте индексы для неактивных разделов НЕПРАВИЛЬНЫМИ.Это исключит время, затрачиваемое на индексацию неактивных данных.

create table tab(active number, col1 number, col2 number, col3 number)
    partition by list(active) 
    (partition tab_active values(1), partition tab_inactive values(0));

create index tab_index1 on tab(col1) local;

alter index tab_index1 modify partition tab_inactive unusable;

Но у этого подхода есть некоторые отрицательные стороны:

  • Не все типы индексов могут быть непригодными для использования.
  • Неправильно иметь непригодные объектыв базе данных.Люди, скорее всего, будут жаловаться на это или предположить, что это ошибка, и перестроить ее.
  • Некоторые операции, такие как усечение, автоматически сделают индексы пригодными для использования снова.12c вы можете сделать это, используя частичные индексы :
    create table tab(active number, col1 number, col2 number, col3 number)
        partition by list(active) 
        (partition tab_active   values(1) indexing on,
         partition tab_inactive values(0) indexing off);
    
    create index tab_index1 on tab(col1) local indexing partial;
    
1 голос
/ 05 октября 2011

Я не думаю, что это возможно.Есть несколько вариантов

  1. Сделать индекс включенным (active, col1 ...), чтобы неактивные элементы не влияли на время запроса так сильно
  2. Создание двух таблиц для активных/ неактивные элементы и управлять активным состоянием, перемещая объекты между двумя таблицами
  3. Создайте вторую таблицу со всеми данными, которые вы хотите проиндексировать, а также уникальный идентификатор и присоединитесь к таблице, чтобы получить остальные данные.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...