Создание индексов для групп по полям? - PullRequest
26 голосов
/ 18 сентября 2009

Вам нужно создать индекс для полей группы по полям в базе данных Oracle?

Например:

select * 
from some_table
where field_one is not null and field_two = ?
group by field_three, field_four, field_five

Я тестировал индексы, созданные для вышеупомянутого, и единственный релевантный индекс для этого запроса - это индекс, созданный для field_two. Другие однополевые или составные индексы, созданные в любом из других полей, не будут использоваться для вышеуказанного запроса. Это звучит правильно?

Ответы [ 3 ]

13 голосов
/ 18 сентября 2009

Это может быть правильно, но это будет зависеть от того, сколько у вас данных. Обычно я создаю индекс для столбцов, которые я использовал в GROUP BY, но в вашем случае оптимизатор мог бы решить, что после использования индекса field_two будет недостаточно возвращаемых данных, чтобы оправдать использование другого индекса для GROUP BY.

9 голосов
/ 18 сентября 2009

Нет, это может быть неверно.

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

В последней статье в моем блоге:

, существует запрос, в котором Oracle не использует полное сканирование таблицы, а объединяет два индекса для получения значений столбца:

SELECT  l.id, l.value
FROM    t_left l
WHERE   NOT EXISTS
        (
        SELECT  value
        FROM    t_right r
        WHERE   r.value = l.value
        )

План:

SELECT STATEMENT
 HASH JOIN ANTI
  VIEW , 20090917_anti.index$_join$_001
   HASH JOIN
    INDEX FAST FULL SCAN, 20090917_anti.PK_LEFT_ID
    INDEX FAST FULL SCAN, 20090917_anti.IX_LEFT_VALUE
  INDEX FAST FULL SCAN, 20090917_anti.IX_RIGHT_VALUE

Как видите, здесь нет TABLE SCAN на t_left.

Вместо этого Oracle получает индексы для id и value, присоединяет их к rowid и получает пары (id, value) из результата объединения.

Теперь по вашему запросу:

SELECT  *
FROM    some_table
WHERE   field_one is not null and field_two = ?
GROUP BY
        field_three, field_four, field_five

Во-первых, он не скомпилируется, поскольку вы выбираете * из таблицы с предложением GROUP BY.

Вам необходимо заменить * на выражения, основанные на столбцах группировки и агрегатах столбцов, не входящих в группу.

Скорее всего, вы получите следующий индекс:

CREATE INDEX ix_sometable_23451 ON some_table (field_two, field_three, field_four, field_five, field_one)

, поскольку он будет содержать все как для фильтрации на field_two, так и для сортировки на field_three, field_four, field_five (полезно для GROUP BY) и проверки того, что field_one равно NOT NULL.

2 голосов
/ 19 сентября 2009

Вам нужно создать индекс для полей группы по полям в базе данных Oracle?

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

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

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

Не всегда. Часто GROUP BY требует, чтобы Oracle выполнил сортировку (но не всегда); и вы можете исключить операцию сортировки, предоставив подходящий индекс для столбцов, которые должны быть отсортированы.

Однако стоит ли вам беспокоиться о производительности GROUP BY, это важный вопрос для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...