Проблема в том, как вы настраиваете свой тест - он нереалистичен и плох для индексов.
Во-первых: у вас в таблице всего два целочисленных столбца, поэтому каждая строка ОЧЕНЬ мала. Таким образом, Oracle может разместить множество строк в каждом блоке базы данных - например, несколько тысяч строк в блоке.
Второе: вы создали свои индексированные данные случайным образом со значениями от 0 до 999.
Соедините эти два факта вместе, и что мы можем догадаться? Ответ: примерно каждый отдельный блок базы данных будет иметь хотя бы одну строку с любым заданным значением столбца B
.
Таким образом, независимо от того, какое значение B
вы ищете, вы будете заканчивать чтение каждого блока в своей таблице по одному (т. Е. «Последовательное чтение»).
Сравните это с планом без индекса - полного сканирования таблицы, - где Oracle будет по-прежнему читать каждый блок, но будет читать их по несколько блоков одновременно (т. Е. "Чтение по отдельности").
Не удивительно, что ваш индекс не помог.
Если вы хотите более качественный тест, добавьте в свою тестовую таблицу столбец C
, представляющий собой строку из 200-300 символов (например, "XXXXXXXXX ..."). Это уменьшит число строк в блоке до более реалистичного значения, и вы должны увидеть лучшие результаты от вашего индекса.
ПОСЛЕДНЕЕ ПРИМЕЧАНИЕ: будьте очень осторожны при использовании индекса BITMAP
. Они практически непригодны для таблиц, в которых есть DML (вставка, обновление, удаление)! Прочитайте все о них прежде, чем использовать один!
UPDATE
Разъяснения по этому вопросу:
Так что, похоже, это немного помогает, но действительно ли это намного дороже средних чисел, чем считать их? И чем дороже среднее число, чем полное сканирование таблицы?
Причина, по которой ваш индекс помог вашему запросу COUNT(*)
, заключается в том, что сам индекс сообщит Oracle, сколько строк соответствует условию B=332
, поэтому ему не нужно читать блоки таблиц и, следовательно, не возникает проблема. Я описал выше (то есть, читая каждый блок таблицы один за другим).
Дело не в том, что COUNT()
"быстрее", чем AVG()
. Просто в вашем тесте COUNT
можно вычислить, используя только индекс, тогда как AVG
нужна информация из таблицы.