Основы проектирования реляционных баз данных

         

Анализ запросов с целью повышения скорости их выполнения


Рассмотрим теперь общую процедуру настройки команды SELECT, результат выполнения которой не удовлетворяет требованиям производительности. Эта процедура является итерацией на пути построения оптимального набора индексов и состоит из семи шагов. При обсуждении этой процедуры мы для простоты будем ориентироваться на СУБД SQLBase.

Шаг 1. Обновить статистику. До того как добавить индексы, необходимо убедиться, что статистика базы данных в системном каталоге является корректной. Если вы выполняете запрос без учета действительной производительности базы данных, вам следовало бы обновить статистику для всех таблиц, указанных в предложении FROM, используя команду UPDATE STSTISTICS (для SQLBаse) или другую специальную команду СУБД. С другой стороны, если вы используете небольшую тестовую базу данных, то можно вручную вычислить необходимые статистические показатели и внести их в системный каталог.

Когда вы обновляете статистику, вам следовало бы скомпилировать команду SQL, установив параметр PLANONLY в положение ON. Сравните новый план запроса со старым до обновления статистики, для того чтобы определить изменения в нем (иногда требуется довольно длительное время для построения плана). Сравнивая планы, можно избежать повторного выполнения запроса только для того, чтобы убедиться, что производительность его выполнения идентична предыдущему выполнению этого запроса. Если статистика изменилась, то выполните запрос, чтобы определить, увеличилась ли производительность и насколько.

Шаг 2. Упростить команду SELECT. Перед добавлением индексов или переписыванием плана выполнения следует попытаться упростить запрос. Задача состоит в том, чтобы сделать выражение SELECT как можно проще, сократив по мере возможности число переменных в нем. Упростив запрос, скомпилируйте команду, чтобы посмотреть план запроса. Сравните новый план запроса со старым. Определите, увеличилась ли производительность запроса, выполнив его.

Для того чтобы упростить SELECT, необходимо:

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


Исключение ненужных предикатов и предложений. Обычно в команду SELECT включают предложений больше, чем это необходимо на самом деле. Так делается для того, чтобы гарантировать корректность ответа, или из-за плохого понимания синтаксиса SQL. До попытки настроить запрос проектировщик базы данных должен удалить все ненужные предложения и предикаты.

Примерами предложений, которые обычно включаются в запрос, но не являются необходимыми, являются следующие:

Предложение ORDER BY. Часто это предложение включается, даже если определенный порядок в результирующем множестве не требуется приложением или конечным пользователем.Предикаты предложения WHERE. Часто это предложение содержит избыточное множество предикатов ограничения. Например, предикаты в следующем предложении WHERE являются избыточными, так как DEPT_NO есть первичный ключ и, следовательно, будет уникально идентифицировать только одну строку:

WHERE DEPT_NO = 10 AND DEPT_NAME = 'PERATIONS'.

Расстановка скобок в арифметических и логических выражениях. Синтаксис SQL SQLBase включает специальные правила предшествования для оценки арифметических и логических выражений. Однако достаточно просто сделать ошибку при применении правил предшествования. Следовательно, мы рекомендуем вам расставлять скобки в этих выражениях для явного определения предшествования в выполнении операций. Вы можете подумать, что оптимизатор оценивает выражения одним способом, а в действительности он поступает по-другому.

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


Природа индексной структуры на основе В-дерева такова, что она может работать с символом подстановки, если он не стоит в начальной позиции строки. Ясно, что оптимизатор не будет использовать индекс, если символ постановки будет стоять на первой позиции (как при использовании связанной переменной в предикате LIKE). В этих случаях будет применено сканирование таблицы.

Преобразовывайте связанные переменные в предикате LIKE в константы для увеличения производительности такого запроса.

Шаг 3. Пересмотреть план запроса. Выполните запрос так, чтобы посмотреть его план. Вы должны хорошо понимать план запроса, чтобы использовать его. Несколько элементов этого плана требуют особого внимания.

Преобразование подзапроса в соединение. Оптимизатор преобразует большинство подзапросов в соединения. Нужно знать, на каких этапах выполнения запроса это преобразование происходит.Когда будут создаваться временные таблицы. Если временные таблицы создаются, это может указывать, что оптимизатор сортирует промежуточные результаты. Если это происходит, можно попробовать добавить индекс на одном из следующих шагов настройки для того, чтобы избежать сортировки.Медленные методы соединения. Хэш-соединение и методы вложенного соединения не являются быстрыми, как метод слияния индексов для больших таблиц. Если эти методы используются, можно попробовать добавить индекс в шагах 5 и 6 настройки команды SELECT, так, чтобы соединения использовали метод слияния индексов. Иногда хэш-соединение может представлять более лучший метод соединения, когда большое количество данных обрабатывается.

Шаг 4. Локализовать узкие места. Запрос, который выполняется медленно, может содержать много предложений и предикатов. Если это так, нужно определить, какие предложения или предикаты приводят к плохой производительности. Если удалить одно или два предложения или предиката, производительность выполнения запроса возрастает значительно. Эти предложения являются критическими параметрами выполнения запроса.

Можно поэкспериментировать с запросом, поочередно удаляя из него предложения или предикаты до тех пор, пока не будет достигнут подходящий уровень производительности.Локализуйте критические предложения и предикаты.

Примеры:

Если запрос содержит предложение ORDER BY, закомментируйте его и посмотрите, изменится ли план этого запроса. Если план изменился, выполните запрос для того, чтобы определить, увеличилась ли производительность.Если запрос содержит несколько соединений, локализуйте то, которое замедляет выполнение. Комментируйте последовательно все соединения, кроме одного, и выполняйте запрос. Определите, какое соединение самое критичное.


Фактор селективности


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

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

Другими словами, если большинство строк таблицы должны быть выбраны, использование индекса повлечет за собой увеличение числа операций ввода/вывода за счет чтения индекса. При этом именно фактор селективности проявляется виртуально в стоимости ввода/вывода, связанной с операцией доступа к индексу, которая используется оптимизатором.

Численно фактор селективности представляет вероятность, которая изменяется от 0 до 1. Умножение числа строк в таблице на фактор селективности для связанного с ним предиката будет давать ожидаемое число строк для операции выборки, при предположении, что значения колонок таблицы равномерно распределены по строкам.



Фактор селективности в случае нескольких предикатов


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

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

Пример. Пусть задан предикат

EMPLOYEE_NO = 45 AND DEPT = 50 AND SALARY > 25000.



Предположим, что индекс определен для составного ключа, содержащего указанные колонки в следующем порядке: EMPLOYEE_NO, DEPT, SALARY. Комбинация факторов селективности для колонки EMPLOYEE_NOи для колонки DEPT, которые появляются в колонке DISTINCTCOUNT строки DEPT таблицы системного каталога SYSKEYS, используется оптимизатором для оценки числа строк, которые будут возвращены по запросу. Действие предиката неравенства для колонки SALARY игнорируется.

Когда для первой по порядку колонки индексного ключа задается предикат неравенства, только фактор селективности этого предиката вычисляется, а все оставшиеся предикаты игнорируются. Пример. Пусть задан предикат

SALARY > 25000 AND DEPT = 50 AND YEARS_SERVICE > 3.

Предположим, что индекс определен для составного ключа, содержащего указанные колонки в следующем порядке SALARY, DEPT, YEARS_SERVICE. Оптимизатор определяет фактор селективности, просматривая корневую страницу индекса для определения числа строк таблицы, для которых выполняется предикат "Зарплата больше 25000". Это значение и становится фактором селективности для всей группы предикатов. Оставшиеся предикаты игнорируются.

Таким образом, на первом шаге своей работы оптимизатор СУБД SQLBase, подготавливая для выполнения команду SQL, строит список вариантов путей доступа, которые могли бы удовлетворить запросу (планы выполнения). Поскольку оптимизатор основан на вычислении стоимости, используется статистика базы данных как основа выполнения оценок того, какая работа требуется для реализации каждого возможного плана выполнения.

Далее оптимизатор запросов строит группу альтернативных планов выполнения, каждый план выполнения оценивается вычислением стоимости так, чтобы наиболее эффективный план мог быть выбран. При этом оцениваются два компонента общей стоимости плана выполнения - требования по вводу/выводу и требования по времени процессора. Выбирается план с наименьшим значением вычисленной стоимости.



Фактор селективности в случае одного предиката


Определение фактора селективности для одного предиката, такого как EMPLOYEE_NO=65, зависит от того, какой оператор используется в предикате. Оператор влияет на фактор селективности, так как он определяет взаимосвязь между строками, которые удовлетворяют предикату и другим операндам.

Чем большее число строк отбрасывает оператор предиката при выборке (ограничивает), тем меньше фактор селективности предиката. Наиболее трудоемким для выполнения оператором (по числу операций ввода-вывода) является оператор равенства, поскольку только одно значение колонки может удовлетворить предикату. В этом случае фактор селективности просто обратно пропорционален кардинальности колонки, которая сохраняется в колонке DISTINCTCOUNT таблицы SYSADM.SYSINDEXES для этой колонки (как индексируемого ключа).

Однако непросто вычислить фактор селективности для операторов неравенства. Рассмотрим следующие два предиката:

ORDER_DATE > JAN-01-1900 ORDER_DATE > SYSDATE -1 DAY

Очевидно, что первый предикат, как можно было бы ожидать, возвратит гораздо больше строк, чем второй, когда будет применен к таблице ORDER.

Как оптимизатор может определить это? Оказывается, что оптимизатор вычисляет фактор селективности посредством доступа к верхнему уровню индекса той индексной структуры, которая содержит колонку запроса (ORDER_DATE). Затем он оценивает число строк, которое удовлетворяет предикату, экстраполируя пропорцию индексных ключей на этом уровне индекса. Этот метод, называемый сканирование B-дерева (B-tree scan), позволяет оптимизатору сделать достаточно точную оценку результатов применения предикатов неравенства.

Другой фактор, который играет роль в определении фактора селективности одного предиката неравенства, есть ответ на вопрос, будет ли сравниваться колонка с константой или связанной переменной? Это некритично для предиката равенства потому, что оптимизатор может вычислить фактор селективности исходя из значения DISTINCTCOUNT в предположении равновероятного распределения значений колонки по строкам таблицы.
Такое предположение позволяет оптимизатору быть нечувствительным к действительным значениям операнда с другой стороны знака равенства. Однако для использования метода сканирования В-дерева оптимизатор должен быть способным найти значение другого операнда. Когда операнд является связанной переменной, оптимизатор должен опуститься назад для проверки предположения, что в действительности трудно закодировать.

Нижеследующая таблица 16.1 суммирует определения фактора селективности для одного предиката, в зависимости от операции и типа второго операнда.

Таблица 16.1. выбор фактора селективности в зависимости от оператора предикатаТип предиката впорядке приоритетаКонстантаНе константа
=1/card1/card
!=,<>1-1/card1/3
>Сканирование индекса1/3
!>Сканирование индекса1/3
<Сканирование индекса1/3
>=Сканирование индекса1/3
<=Сканирование индекса1/3
BetweenСканирование индекса1/3
Null-Не используется
ExistsПреобразованиеПреобразование
LikeСканирование индексаНе определен
InПреобразованиеПреобразование

Использование оптимизатора для оптимизации выполнения запросов


При создании физической модели реляционной базы данных мы рассмотрели общие принципы и эвристические правила создания внутренней схемы, которая обеспечивает хорошие характеристики производительности для большинства SQL запросов. Однако методики физического проектирования не гарантируют того, что некоторые запросы будут иметь хорошие характеристики производительности без дальнейшей настройки.

Существует много вариантов увеличения производительности запросов. Основной идеей для выбора самого подходящего является построение запроса таким образом, чтобы оптимизатор запросов СУБД вычислил оптимальные по стоимости пути доступа для его выполнения.

Так, например, при работе с оптимизатором СУБД SQLBase для увеличения производительности конкретной команды SELECT, проектировщик базы данных или администратор баз данных выполняет следующие действия:

Обновление статистики.Определение оптимального набора множества индексов.Переписывание плана выполнения запроса, выбранного оптимизатором.

Обновление статистики. Статистика в СУБД SQLBase поддерживается независимо как для таблиц, так и для индексов. Оптимизатор использует эти статистики для вычисления стоимости различных путей доступа. Следовательно, первым аспектом работы с оптимизатором запросов, для улучшения производительности данного запроса, является гарантия того, что эти статистики корректны и обновляемы.

Оптимальное множество индексов. Другим аспектом работы с оптимизатором запросов является добавление индексов для увеличения скорости выполнения секций и соединений, оценки сортировки в предложениях GROUP BY и ORDER BY. Если утверждение SELECT выполняется медленно, то это, вероятно, либо соединение, сортировка, либо чтение большой таблицы. Индексы могут увеличить производительность всех этих операций.

Общая стратегия индексирования состоит в создании индексов для всех первичных и внешних ключей. Это так, потому что в большинстве систем существуют колонки, которые извлекаются гораздо чаще в предикатах предложений WHERE, GROUP BY, ORDER BY.
Этот первоначальный набор индексов базы данных обеспечивает индексацию для выполнения селекции и исключений сортировок первичных и внешних ключей. Следовательно, часто соединения являются наиболее критическим временным аспектом конкретного запроса. Самый быстрый алгоритм соединения для больших таблиц есть объединение индексов. Первоначальный набор индексов гарантирует, что путь доступа с объединением индексов доступен для оптимизатора запросов, когда колонка соединения является первичным или внешним ключом. Для всех других соединений оптимизатор ограничивается более медленными алгоритмами соединения, хэш-соединением или одним из алгоритмов соединения в цикле. Однако для большинства утверждений SELECT пути доступа, допустимые для оптимизатора на первоначальном наборе индексов, обеспечивают адекватную производительность.

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

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

Следовательно, общая цель проектирования состоит в том, чтобы создать набор индексов, который отвечает требованиям производительности для всех транзакций к базе данных. Это и есть оптимальный набор индексов.

Переписывание плана выполнения запроса, выбранного оптимизатором. В СУБД SQLBase такая процедура выполняется с помощью настройки команды SELECT. Она может быть применена в при использовании других реляционных СУБД.

Однако в некоторых СУБД, например СУБД Oracle, проектировщик базы данных может явно влиять на выбор тех или иных вариантов улучшения скорости выполнения запросов.



На уровне экземпляра режим работы оптимизатора задается администратором базы данных. На уровне сессии используется команда вида

ALTER SESSION SET OPTIMIZER_GOAL = <режим>;

В качестве режима может быть задано одно из следующих значений:

CHOOSE - это значение задает использование оптимизации, основанной на вычислении стоимости, в противном случае будет использоваться оптимизация, основанная на правилах;RULE - это значение задает использование оптимизации, основанной на правилах. Такой режим оптимизации будет применен и при использовании подсказок (см. таблицу 16.2);

Таблица 16.2. ПодсказкаОписание
ROWIDИспользование идентификатора
CLUSTERСканирование ключа кластера
HASHСканирование хэш-индекса
INDEXСканирование индекса
INDEX_ASCСканирование индекса в порядке возрастания
INDEX_DECSСканирование индекса в порядке убывания
AND_FFSБыстрое полное сканирование индекса
AND_EQUALИспользование нескольких индексов со слиянием результатов
FULLПолное сканирование таблицы
FIRST_ROWS - это значение задает минимизацию времени отклика, т.е. сведение к минимуму временного интервала от начала выполнения запроса и до возвращения первой строки результата в приложение;ALL_ROWS - это значение задает использование оптимизации, основанной на вычислении стоимости, для минимизации общего количества строк, обрабатываемых системой в единицу времени (число транзакций в секунду).

Более подробно об использовании оптимизатора запросов СУБД Oracle можно прочитать в рекомендованной к лекции литературе.



Для управления оптимизатором СУБД Oracle используются специальные подсказки, которые записываются в SQL-командах. Такие подсказки влияют на выбор конкретного способа обращения к данным. Пример ниже содержит подсказку оптимизатора для использования индекса (в предположении, что таблица имеет один индекс):

Пример

SELECT /* + index */ EMPLOYEE_NO, DEPT, SALARY FROM EMPLOYEE WHERE EMPLOYEE_NO = 65;

Подсказка является частью комментария, следующего за ключевым словом команды, и отмечается символом "+".

Для эффективного переписывания плана выполнения запроса необходимо в течение некоторого времени накопить знания о работе СУБД с базой данных, в частности, определить список проблемных запросов и их характеристик. При решении задач оптимизации проблемных запросов нужно следовать следующим рекомендациям:

При необходимости доступа к значительной части строк какой-либо таблицы полное сканирование таблицы предпочтительнее, чем использование индексов. Это связано с дополнительным чтением записей индекса. Индексы, как правило, эффективны, если запрос захватывает до 10% строк таблицы. Для небольших таблиц использование индексов практически неэффективно.На различных этапах выполнения запросов следует максимально использовать результаты предыдущих этапов, чтобы не переписывать лишний раз результирующий набор как результат выполнения команды. Например, если результирующий набор данных требуется отсортировать по значениям некоторой колонки, то при выполнении соединения таблиц можно указать способ выполнения этой операции, при котором будет проведена сортировка этих значений. Полученные результаты будут использованы при окончательной сортировке.При использовании различных видов подзапросов на основе знаний о данных следует учитывать особенности выполнения предикатов и операторов теоретико-множественных операций.

Одним из важных вопросов при работе с оптимизатором запросов является выбор режима его работы (если такая возможность предоставляется СУБД). Так, для оптимизатора СУБД Oracle режим оптимизации может быть задан на уровне экземпляра базы данных, на уровне сессии или SQL-команды.

Реализация оптимизатора SQLBase


На примере оптимизатора СУБД SQLBase рассмотрим основные принципы реализации оптимизаторов обработки запросов, основанных на вычислении стоимости, и покажем, как использовать эти принципы в случае ручной настройки запросов.



Статистика базы данных


Когда оптимизатор запросов SQLBase осуществляет выбор пути доступа, он использует статистику базы данных для оценки стоимости, связанной с каждым вариантом пути доступа, т.е. планом выполнения. Эта статистика, которая сохраняется в системном каталоге SQLBase, связана с различными таблицами и индексами, содержащимися в базе данных. Часть статистических данных поддерживается динамически, т.е. сервер SQLBase сам поддерживает ее обновление во время обычных операций сервера. Однако большая часть статистической информации поддерживается статически, т.е. она вычисляется и сохраняется, когда происходят определенные события.

Событие, которое обычно приводит к обновлению статистики базы данных, есть выполнение команды SQL UPDATE STATISTIC. Эта команда проверяет таблицы и индексы базы данных, вычисляет требуемые статистические показатели и затем сохраняет их в соответствующих таблицах системного каталога. Статистика также создается для индексов или таблиц при их первоначальном создании. Если никаких строк не вставляется в таблицы и индексы до момента обновления статистики по команде SQL UPDATE STATISTIC, то статистические показатели устанавливаются к значениям по умолчанию.

Как правило, статистика базы данных может быть обновлена администратором базы данных. После выполнения обновления пути доступа выбираются оптимизатором на основе вычисления стоимости по статистике, сохраненной в системном каталоге. В этом случае системный администратор может влиять на выбор путей доступа оптимизатором, исходя не из текущего содержания базы данных, а из ее предполагаемого содержания в будущем. Для того, чтобы точно вычислить и сохранить эту статистику, системный администратор должен знать, что эта статистика означает.

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



Статистика индексов


Статистика, связанная с индексами таблицы, также поддерживается в двух отдельных таблицах системного каталога. Все колонки (за исключением одной - HEIGTH - в таблице SYSINDEXES) поддерживаются статически и заполняются, когда выполняется команда UPDATE STАTISTICS или создается индекс.

В таблице SYSADM.SYSINDEXES статистическая информация поддерживается в следующих колонках:

HEIGTH. Высота индексного дерева есть число узлов, которые нужно прочитать начиная с корневого уровня и заканчивая уровнем листьев включительно. Также она называется глубиной дерева (depth). Этот статистический показатель также поддерживается и динамически в странице управления индексами. Это поле равно нулю для хэш-индекса.LEAFCOUNT. Общее число узлов на нижнем уровне (число листьев) индекса равно значению, сохраняемому в этой колонке. Также это есть число страниц в подмножестве индексной последовательности. Равно нулю для хэш-индеса.CLUSTERCOUNT. Общее число изменений страниц, которое происходило бы, если вся таблица была прочитана через подмножество индексной последовательности. Для полностью кластеризованного индекса эта колонка равна числу основных страниц данных в таблице. С другой стороны, наибольшее значение для общего некластеризованного индекса равно числу строк в таблице. Равно нулю для хэш-индекса.PRIMPAGECOUNT. Число базовых страниц, которые были распределены основной таблице для размещения в хэш-индексе. Это есть число слотов хэширования доступных для распределения строк. Равно нулю для В+-индекса.OVFPAGECOUNT. Эта колонка содержит число страниц переполнения, которые распределены таблицы для размещения в хэш-индексе. Когда таблица и индекс первоначально создаются, это число отражает число страниц переполнения, которое предполагается распределить. Затем это число увеличивается, когда дополнительная страница переполнения требуется для разрешения коллизии при хэшировании. Это поле равно нулю для В+-индекса.AVRKEYLEN. Для В+-индексов эта колонка содержит среднюю длину ключа для всех входов индекса.
Это число необходимо для того, чтобы поддерживать все входы индекса как данные с переменной длиной. Это поле равно нулю для хэш-индексов.

В таблице SYSADM.SYSKEYS поддерживается следующая статистическая информация.

DISTINCTCOUNT. Эта колонка содержит число различных ключей в индексе. Для каждой из существующих возможных комбинаций значений составного ключа существует это число, равное произведению кардинальности каждой колонки составного ключа. Кардинальность (cardinality) равна числу различных значений, которые колонка имеет в таблице.

Простейший пример есть колонка Пол (SEX_CODE), которая имеет кардинальность 2. Рассмотрим следующий индекс:

CREATE INDEX XNKSALS ON EMPLOYEE (DEPT, SALARY, YEARS_SERVICE);

Таблица EMPLOYEE содержит 250 строк, по одному для каждого служащего компании. Кардинальность множества значений колонок есть:

DEPT 10.SALARY - никакие два служащих компании не имеют одинаковой зарплаты, т.е. 250.YEARS_SERVICE - компания прошла три различных временных периода, т.е. 3.

При этих заданных условиях строки таблицы, которые описывают эти индексируемые колонки, имеют следующие значения DISTICTCOUNT:

DEPT 10, по одному для каждого отдела в компании.SALARY - 250. Так как каждый служащий имеет дискретное значение зарплаты, число ключей в этой точке индекса равно числу строк в таблице. Альтернативно, если существует только пять размеров зарплат, выплачиваемых компанией, и каждый отдел имеет кого-нибудь с этими пятью размерами зарплат, то DISTICTCOUNT равно 50 (=5*10).YEARS_SERVICE - 250. Так как поле зарплаты имеет уже кардинальность, равную числу строк в таблице, это поле не может превышать этого значения. Можно ожидать, что число входов индекса на каком-либо уровне может превысить число строк в таблице.


Статистика таблиц


Статистика, связанная с таблицами базы данных, поддерживается в двух различных таблицах системного каталога, каждая из которых описывается ниже. Все колонки, не указанные специально как динамически поддерживаемые, являются статическими и заполняются при выполнении команд UPDATE STATISTIC или CREATE.

В таблице системного каталога SYSADM.SYSTABLES для сохранения статистики используются следующие колонки:

ROWCOUNT. Значение этой колонки есть число строк в таблице. Этот статистический показатель поддерживается динамически в странице управления таблицей (table's control page), и принимает конкретное значение при выполнении команды UPDATE STATISTIC.PAGECOUNT. Значением этой колонки является общее число страниц данных в таблице. Этот статистический показатель также поддерживается динамически, но принимает конкретное значение только когда команда UPDATE STATISTIC выполняется. Когда эта колонка поддерживается системой, она всегда будет суммой двух нижеследующих колонок ROWPAGECOUNT и LONGPAGECOUNT. Если DBA устанавливает этот статистический показатель явно, то указанное соотношение может не выполняться.ROWPAGECOUNT. Эта колонка содержит число основных станиц строк, занятых под таблицу, плюс число всех страниц расширения, которые могут быть распределены для таблицы. Этот динамический статистический показатель генерируется только по команде.LONGPAGECOUNT. Эта колонка содержит число страниц, распределенных таблице для колонок типа LONG VARCHAR. Этот динамический статистический показатель генерируется только по команде.EVENT_PAGECOUNT. Эта колонка содержит среднюю долю данных, сохраненных в основных станицах строк и страницах расширения. Это число не включает страницы для длинных строк.AVRROWLEN. Эта колонка содержит действительную среднюю длину строк в таблице. Это значение может значительно отличаться от заданной длины строки, так как СУБД SQLBase сохраняет все колонки как данные переменной длины, независимо от типа данных, используемого в определении колонок. Заметим, что эта длина строки является только длиной строки, сохраняемой в основной странице и странице расширения, и, следовательно, исключает все колонки типа LONG VARCHAR.AVRROWLONGLEN. Эта колонка содержит действительную среднюю длину всех колонок типа LONG VARCHAR, хранимых в таблице. Она будет содержать нуль, если переменных такого типа в таблице нет.

В таблице системного каталога SYSADM.SYSCOLUMNS поддерживается следующая статистическая информация:

AVRCOLLEN. Эта колонка содержит действительную среднюю длину данной колонки для всех строк таблицы. Это значение может значительно отличаться от заданной при определении длины колонки, так как СУБД SQLBase сохраняет все колонки как данные переменной длины. Основная страница строки хранит описание длины данных для каждой непустой колонки.AVRCOLLONGLEN. Эта колонка содержит действительную длину колонки типа LONG VARCHAR для всех строк в таблице. Это значение равно нулю, если такие колонки отсутствуют в таблице.