Индекс Oracle едва ускоряет совокупные вычисления - PullRequest
0 голосов
/ 12 сентября 2018

Я создал таблицу с двумя столбцами, a и b.Колонка А - это просто цифры от 1 до 100 миллионов.Столбец b представляет собой случайное целое число от 0 до 999 включительно.Я хотел использовать эту таблицу, чтобы проверить, как индексы улучшают вычисления.Поэтому я проверил следующее:

select count(*) from my_table where b = 332 

select avg(a) from my_table where b = 387

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

Затем я создалindex:

create bitmap index myindx1 on my_table (b);
commit;

Это уменьшило счет (*) с 14 до 75 миллисекунд, успех!

Но средняя (а) не очень хорошо себя чувствовала.На самом деле все стало еще хуже: от 8 до 10 секунд.Я не проверял это много раз и, основываясь на планах, это выглядит как случайность, но, по крайней мере, он, кажется, не работает намного лучше, чем я ожидал.

План объяснения без индекса выглядит следующим образом:

explain plan without index

План объяснения с индексом выглядит следующим образом:

explain plan with index

Похоже, это немного помогает, но действительно ли это намного дороже, чем средние числа, чем считать их?И чем дороже среднее число, чем полное сканирование таблицы?Я думал, что этот индекс сократит мой запрос на долю от первоначальной стоимости, а не просто сэкономит немного времени.Что еще я могу сделать, чтобы ускорить этот запрос?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Растровые индексы не должны использоваться в системах OTLP.Их стоимость обслуживания слишком высока.

IHMO чистый B * индекс дерева будет достаточно.ДИАПАЗОН ИНДЕКСА СКАНИРУЕТ от корневого до самого высокого значения подъема листьев «332», а затем выполняет итерацию слева направо, посещая все листья, имеющие одинаковое значение «В».Это все, что вы хотите.

Если вы хотите еще больше ускорить его, вы можете создать так называемый индекс покрытия.Поместите оба столбца «B» и «A» (в этом порядке) в указатель.Тогда вы не будете искать в таблице значение «A», когда «B» соответствует.Это особенно полезно, если таблица содержит много столбцов, которые вам не нужны.

0 голосов
/ 12 сентября 2018

Проблема в том, как вы настраиваете свой тест - он нереалистичен и плох для индексов.

Во-первых: у вас в таблице всего два целочисленных столбца, поэтому каждая строка ОЧЕНЬ мала. Таким образом, Oracle может разместить множество строк в каждом блоке базы данных - например, несколько тысяч строк в блоке.

Второе: вы создали свои индексированные данные случайным образом со значениями от 0 до 999.

Соедините эти два факта вместе, и что мы можем догадаться? Ответ: примерно каждый отдельный блок базы данных будет иметь хотя бы одну строку с любым заданным значением столбца B.

Таким образом, независимо от того, какое значение B вы ищете, вы будете заканчивать чтение каждого блока в своей таблице по одному (т. Е. «Последовательное чтение»).

Сравните это с планом без индекса - полного сканирования таблицы, - где Oracle будет по-прежнему читать каждый блок, но будет читать их по несколько блоков одновременно (т. Е. "Чтение по отдельности").

Не удивительно, что ваш индекс не помог.

Если вы хотите более качественный тест, добавьте в свою тестовую таблицу столбец C, представляющий собой строку из 200-300 символов (например, "XXXXXXXXX ..."). Это уменьшит число строк в блоке до более реалистичного значения, и вы должны увидеть лучшие результаты от вашего индекса.

ПОСЛЕДНЕЕ ПРИМЕЧАНИЕ: будьте очень осторожны при использовании индекса BITMAP. Они практически непригодны для таблиц, в которых есть DML (вставка, обновление, удаление)! Прочитайте все о них прежде, чем использовать один!

UPDATE

Разъяснения по этому вопросу:

Так что, похоже, это немного помогает, но действительно ли это намного дороже средних чисел, чем считать их? И чем дороже среднее число, чем полное сканирование таблицы?

Причина, по которой ваш индекс помог вашему запросу COUNT(*), заключается в том, что сам индекс сообщит Oracle, сколько строк соответствует условию B=332, поэтому ему не нужно читать блоки таблиц и, следовательно, не возникает проблема. Я описал выше (то есть, читая каждый блок таблицы один за другим).

Дело не в том, что COUNT() "быстрее", чем AVG(). Просто в вашем тесте COUNT можно вычислить, используя только индекс, тогда как AVG нужна информация из таблицы.

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