Работают ли индексы с групповой функцией в oracle? - PullRequest
4 голосов
/ 17 октября 2011

Я выполняю следующий запрос.

SELECT Table_1.Field_1,
           Table_1.Field_2,
           SUM(Table_1.Field_5) BALANCE_AMOUNT
      FROM Table_1, Table_2
     WHERE Table_1.Field_3 NOT IN (1, 3)
       AND Table_2.Field_2 <> 2
       AND Table_2.Field_3 = 'Y'
       AND Table_1.Field_1 = Table_2.Field_1
       AND Table_1.Field_4 = '31-oct-2011'
     GROUP BY Table_1.Field_1, Table_1.Field_2;

Я создал индекс для столбцов (Field_1,Field_2,Field_3,Field_4) из Table_1, но индекс не используется.

Если я уберу SUM(Table_1.Field_5) из предложения select, index будет использоваться.

Я запутался, если оптимизатор не использует этот индекс или его из-за функции SUM(), которую я использовал в запросе.

Пожалуйста, поделитесь своим объяснением с тем же.

Ответы [ 4 ]

6 голосов
/ 17 октября 2011

При удалении СУММЫ вы также удаляете field_5 из запроса.Все данные, необходимые для ответа на запрос, затем можно найти в индексе, который может быть быстрее, чем сканирование таблицы.Если вы добавили field_5 к индексу, запрос с SUM может использовать индекс.

3 голосов
/ 17 октября 2011

Если ваш запрос возвращает большой процент строк таблицы, Oracle может решить, что выполнить полное сканирование таблицы дешевле, чем «переключение» между индексом и кучей таблицы (чтобы получить значения в Table_1.Field_5).

Попробуйте добавить Table_1.Field_5 к индексу (таким образом, охватывая весь запрос индексом) и посмотрите, поможет ли это.

См. Сканирование только по индексу: предотвращение доступа к таблице Используйте The Index Luke для концептуального объяснения происходящего.

1 голос
/ 17 октября 2011

Как вы упомянули, наличие функции суммирования приводит к тому, что индекс игнорируется.

Есть индексы на основе функций :

Индекс на основе функций включает столбцы, которые либо преобразуются функцией, такой как функция UPPER, либо включаютсяв выражении, таком как col1 + col2.

Определение индекса на основе функции для преобразованного столбца или выражения позволяет возвращать эти данные с использованием индекса, когда эта функция или выражение используется в предложении WHERE илиЗАКАЗАТЬ ПОЛОЖЕНИЕ.Поэтому индекс на основе функций может быть полезен, когда часто выполняемые операторы SQL включают преобразованные столбцы или столбцы в выражениях в выражении WHERE или ORDER BY.

Однако, как и во всех случаях, на основе функцийиндексы имеют свои ограничения:

Выражения в индексе на основе функций не могут содержать никаких агрегатных функций.Выражения должны ссылаться только на столбцы в строке в таблице.

0 голосов
/ 20 августа 2017

Хотя я вижу здесь несколько хороших ответов, пару важных моментов упущены -

SELECT Table_1.Field_1,
           Table_1.Field_2,
           SUM(Table_1.Field_5) BALANCE_AMOUNT
      FROM Table_1, Table_2
     WHERE Table_1.Field_3 NOT IN (1, 3)
       AND Table_2.Field_2 <> 2
       AND Table_2.Field_3 = 'Y'
       AND Table_1.Field_1 = Table_2.Field_1
       AND Table_1.Field_4 = '31-oct-2011'
     GROUP BY Table_1.Field_1, Table_1.Field_2;

Сказать, что наличие в предложении select значения SUM (Table_1.Field_5) приводит к тому, что индекс не будет использоваться в неверном виде.Ваш индекс на (Field_1,Field_2,Field_3,Field_4) все еще может быть использован.Но есть проблемы с вашим индексом и SQL-запросом.

Так как ваш индекс только на (Field_1,Field_2,Field_3,Field_4), даже если ваш индекс используется, БД будет вынужден получить доступ к фактической строке таблицы, чтобы получить Field_5 для применения фильтра.Теперь это полностью зависит от плана выполнения, составленного из оптимизатора SQL, который является экономически эффективным.Если оптимизатор SQL обнаружит, что full table scan имеет меньшую стоимость, чем использование индекса, он будет игнорировать индекс.Скажем так, теперь я расскажу вам о возможных проблемах с вашим индексом -

  1. Поскольку у других есть состояния, вы можете просто добавить Field_5 в индекс, чтобы не требовался отдельный доступ к таблице.
  2. Ваш порядок индекса очень важен для производительности.Например,в вашем случае, если вы отдадите ордер как (Field_4,Field_1,Field_2,Field_3), это будет быстрее, так как у вас есть равенство в Field_4 - Table_1.Field_4 = '31-oct-2011'.Подумайте, это было -

Table_1.Field_4 = '31-oct-2011' даст вам меньше возможностей для выбора окончательного результата, чем Table_1.Field_3 NOT IN (1, 3).Вещи могут измениться, так как вы делаете соединение.Всегда лучше увидеть план выполнения и соответствующим образом спроектировать индекс / sql.

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