|
Программирование >> Проектирование баз данных
шестибайтных значений столбца вырастет до четырех уровней, когда число элементов индекса превысит 2000000, и (в зависимости от степени сжатия блоков-ветвей) останется на этом же уровне для миллиардов строк. Что касается чтения с диска, то, как правило, осуществляется чтение не более двух нижних уровней, поскольку первые два уровня часто используемых индексов обычно кэщируются в SGA. 2. Корневой узел и узлы-ветви индекса сжимаются, поэтому они содержат ровно столько начальных байтов значения, сколько нужно для того, чтобы отличить его от других значений. Узлы-листья содержат полное значение. Это позволяет выполнить некоторые запросы только при помощи индекса, т.е. без обращения к блоку данных: SELECT COUNT(*) FROM employees emp WHERE emp.ename LIKE S%; Однако это сработает лищь при условии, что столбец ENAME определен как NOT NULL (поскольку неопределенные значения не индексируются). 3. Значения в индексе упорядочиваются по ключевому значению, а блоки индексов связываются в двунаправленный список. Это обеспечивает последовательный доступ к индексу и позволяет использовать индекс для выполнения операции ORDER BY в запросе. 4. Индекс, имеющий структуру В*-дерева, можно применять как для поиска точного соответствия, так и для поиска диапазона значений: ename < JONES, ename BETWEEN JONES AND SMITH 5. Индексы, имеющие структуру В*-дерева, могут охватывать несколько столбцов таблицы (такие индексы называются составными). Оптимизатор может использовать составные индексы только там, где задана лидирующая часть индекса. Например, индекс по столбцам (ENAME, JOB) при выполнении запроса SELECT * from employee emp WHERE emp.30b = SALES; применяться не будет, поскольку лидирующая его часть (ENAME) в запросе не указана. 6. Оптимизатор Oracle сам примет решение о том, использовать индекс или нет, если мы не повлияем на него посредством подсказки или путем изменения SQL-запроса. 7. Неопределенные значения не индексируются. Если столбец, для которого рассматривается возможность индексирования, допускает неопрсделер!-ные значения, то оптимизатор откажется применять его в определенных операциях, которые, по вашему мнению, могут выполняться с использованием индекса. Самый очевидный пример - ORDER BY. Oracle fre хранит в индексах полностыо неопределенные ключи, но сохранит в индексе частично Неопределенный составной ключ. В этом случае СУБД классифицирует одно неопределенное значение как равное другому неопределенному значению с целью соблюдения ограничении PRIMARY KEY и UNIQUE. Она даже примет неопределенное значение как лидирующую часть составного индексного ключа и сохранит этот ключ в индексе, но откажется использовать этот индекс для поиска строк, у которых значение лидирующей части кдюча не определено. 8. Блоки-ветви не удаляются (кроме как в операции TRUNCATE над базовой таблицей или кластером). Корпорация Oracle утверждает, что это ограничение существенно помогает в реализации настоящего блокирования на уровне строк. Но ведь этим свойством обладала и Oracle версии 5, где блокировки на уровне строк не было! 9. Блоки-листья повторно заполняются лишь в том слугае, если становятся совершенно пустыми (и даже это - относительно недавнее новшество; пространство блоков-листьев обычно никогда не восстанавливалось). Таким образом, даже в текущих версиях индексы, страдающие от высокой интенсивности вставок и удалений, часто заполняются, главным образом, невосстановленным пространством из удаленных элементов. Отключение индексов Одно из важных качеств хорошего проектировщика - прагматизм. Что мы делаем, когда проектируем два модуля с совершенно разными требованиями к индексам для одной таблицы? Ущемляем один модуль в пользу другого? Нет, обычно мы стараемся обеспечить приемлемые условия для обоих модулей. Самый простой конфликт, который приходится разрешать, - это конфликт между запускающейся раз в сутки пакетной программой, выполняющей интенсивное обновление таблицы (для быстрой работы этой программы нужно минимизировать число индексов), и оперативной программой, которой требуется множество индексов для поддержки гибкого поиска. В данном случае мы просто заставляем пакетную программу удалить индексы перед началом работы и пересоздать их после ее завершения. Если эта программа работает во время оперативного соединения, то, возможно, ей придется потерпеть. Можно ли отключить индекс в запросе? Мы говорили, что индексы не всегда оказывают положительное влияние на производительность запросов. Давайте рассмотрим крайний случай. Представьте, что вся таблица EMPLOYEE, изображенная на рис. 6.4, читается с использованием индекса. Читать индексные блоки достаточно легко, так как они связаны, а элементы индекса упорядочены. Однако, как видно из указателей на блоки данных на рис. 6.4, строки данных находятся в разных местах. Если читать таблицу с использованием индекса, то придется перечитывать один и тот же блок данных несколько раз. В данном случае эффективнее выполнить полное сканирование таблицы и читать блоки данных по одному. Благодаря имеющейся в Oracle? возможности чтения с упреждением, при полном сканировании таблицы мы фактически читаем несколько блоков в одной операции вБода-вывода (точное количество задается в параметре инициализации сервера DB FILE MULTIBLOCK READ COUNT). Должен существовать момент, когда более эффективным становится сканирование таблицы, а не использование индекса. Чтобы его установить, определите количество индексов и элементов данных в блоке и число уровней в индексе, а затем сравните количество логических операций ввода-вывода для каждого метода. Существует и общее эмпирическое правило - если ожидается, что число возвращаемых строк превысит 15-20% от числа строк в таблице, то, вероятно, лучще использовать полное сканирование таблицы. (Оптимизатор по стоимости, кажется, применяет в качестве точки отключения индексов значение 5%, что, конечно, очень мало.) Как явно отключить индекс в запросе? В Oracle версии 6 это делалось ггутем определенной модификации индексированного столбца. Вот несколько примеров; SELECT * FROM employee emp /* конкатенировать пустую строку с символьным столбцом */ WHERE emp.ename] Г = SMITH; SELECT * FROM employee emp /* использовать функцию, которая не влияет на смысл */ WHERE UPPER(emp.ename) = SMITH; SELECT * FROM employee emp /* добавить нуль в числовые столбцы */ WHERE emp.empno + О = 1234; Из-за методов упорядочивания индекса и проведения поиска в нем всякая трансформация, влияющая на значение столбца и, следовательно, на его положение в индексе, приводит к тому, что индекс для поиска данного элемента использоваться не будет. В Oracle? индекс отключается через подсказку оптимизатору. Этот метод имеет ряд существенных преимуществ: он более понятен и очевиден для читающего SQL-запрос; работает быстрее. Показанные в примерах выше лишние операции фактически выполняются, на что требуется довольно много процессорного времени. Известных недостатков у него нет, особенно сейчас, когда версия 7.3 выдает предупреждение, если не может понять подсказку или отказывается Принять ее. Вот пример подсказки оптимизатору: SELECT /*+ FULL(EMP) */ FROM employees emp с , WHERE emp.ename = SMITH; ; , . i
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |