Как уже отмечалось в предыдущей лекции, одна из важнейших задач физического
О
Концептуально действие индекса состоит в следующем. В индексе содержится упорядоченный список значений колонки или комбинации колонок, а также сведения о местонахождении на жестком диске соответствующих этим значениям строк таблицы. Значения колонки в индексе упорядочены. Несмотря на то, что порядок строк в таблице случаен, индекс можно быстро просмотреть, чтобы найти конкретное значение. Упорядоченный индекс можно просмотреть во много раз быстрее, чем неупорядоченную таблицу. Чем выше степень различия значений ключа в колонке, тем быстрее будет выполняться доступ к строкам этой таблицы.
Так при вставке новой записи в таблицу проверка уникальности первичного ключа реализуется не реальным просмотром индекса, а тем, что требование уникальности предъявляется к значениям колонки первичного ключа в индексе. Таким образом, индекс - это объект базы данных, который может существенно сократить время поиска нужных строк в таблице.
Замечание. После того как вы создали индекс, оптимизатор СУБД, о котором пойдет речь в последней лекции, будет использовать его всякий раз, когда это ускоряет считывание данных. Обратите внимание на то, что созданный вами индекс может ни разу не использоваться!
Индексы, несомненно, занимают место в базе данных. При вводе новых данных или удалении данных СУБД приходится обновлять и таблицы, и индексы. Это может замедлить выполнение операций модификации данных, особенно для таблиц с большим числом строк. Таким образом, может возникнуть проблема, суть которой состоит в возникновении конфликта между скоростью обновления данных в таблице и скоростью ее считываний. При разрешении этой проблемы следует придерживаться следующего эмпирического правила: создавайте индексы для колонок первичных ключей и других колонок, часто используемых в тех запросах, в которых для выборки данных применяются логические критерии. Если в результате скорость обновления данных ухудшается, то можно рассмотреть вопрос об удалении некоторых индексов.
Каждая таблица базы данных может иметь один или несколько индексов. Индексы могут создаваться по одной колонке или нескольким колонкам таблицы. Колонки, входящие в индекс, принято называть
В СУБД Oracle и SQLBase каждая строка таблицы обладает уникальным идентификатором ROWID - идентификатором строки, который представляет собой псевдоколонку с информацией о точном расположении строки в базе данных и содержит еще некоторую идентифицирующую информацию (
Зачем создавать индекс для колонки или группы колонок? Это важный вопрос, и мы на него можем ответить следующим образом:
На этапе физического
Чтобы решать эти задачи, проектировщик базы данных должен знать, как работает индекс, какие типы индексов поддерживает СУБД, а также понимать смысл методов индексирования.
Сначала мы опишем типы индексов вместе с методами индексирования для каждого типа, затем разберем вопрос о том, как работает индекс, и в заключение дадим некоторые рекомендации по созданию и использованию индексов.
Индекс на основе сбалансированной иерархической структуры, или индекс B-Tree (Balanced
(рис 11.1) Концептуальная организация B-Tree индекса
Замечание. Следует отметить два случая, когда после выборки идентификатора строки из индекса может понадобиться несколько посещений
физической страницы индекса: 1) когда строка имеет длину более однойфизической страницы , так называемая расщепленная строка; 2) когда строка за время своего существования в базе данных увеличилась и была перемещена из исходной страницы в другую, так называемая мигрировавшая строка.
Индекс B-Tree характеризуется количеством уровней в индексе (height). Чем меньше уровней, тем выше производительность.
Индекс B-Tree - это физический объект реляционной базы данных, организованный по принципу сбалансированной иерархической структуры и обладающий набором свойств. Сформулируем некоторые свойства индексов со структурой B-Tree.
ORDER BY в запросе.{Ename, Job} для обработки запросаSELECT * FROM EMPLOYEE WHERE Job='Инженер';применяться не будет.
NULL не индексируются. Если для таких колонок строится индекс, то СУБД будет отказываться примерять его в некоторых операциях, например ORDER BY.Индексы создаются командой SQL CREATE INDEX. В предыдущих лекциях мы уже создавали индексы на основе B-Tree. При
Пример. В нашей учебной базе создадим для таблицы
EMPLOYEEсоставной индекс по колонкамEname и Job. При этом проектировщик базы данных не уверен, что этот индекс будет использоваться эффективно, поэтому он задал опцию для сбора статистики для этого индекса.
CREATE INDEX emp_ndx2 ON EMPLOYEE (Ename, Job) COMPUTE STATISTICS;
В этом подразделе мы рассмотрели наиболее часто используемый тип индексов. В последующих подразделах и разделах мы рассмотрим другие типы индексов реляционных баз данных.
Индексы могут создаваться на основе значений одной или нескольких колонок. Если требования к данным в запросе удовлетворяются на основе информации из связанного с этими данными индекса, то доступ к CREATE TABLE, как показано в примере ниже.
Пример. Предположим, что в нашей учебной базе требуется в отдельной таблице сохранять и отслеживать проблемы, возникающие по выполнении всех проектов, и частоту возникновения проблемы. Создадим
исключительно индексную таблицу для этой таблицы, как показано ниже:
CREATE TABLE Proj_Index
( projno char(8) NOT NULL,
t_person char(32) NOT NULL,
t_frequency integer,
t_problem varchar2(512),
CONSTRAINT pk_ndx PRIMARY KEY( projno, t_person) )
ORGANIZATION INDEX
TABLESPACE ts_ndx1
PCTTHRESHOLD 20
INCLUDING t_frequency
OVERFLOW TABLESPACE ts__of_ndx1;
Команда CREATE TABLE не отличается ничем от других команд создания таблиц до тех пор, пока не встретится предложение ORGANIZATION INDEX, которое указывает СУБД на создание PCTTHRESHOLD указывает, что оставшуюся часть строки нужно сохранять в заданном INCLUDING определяет имя колонки, с которой строка индексной таблицы делится на две части: индексную и переполнения. Эта колонка может быть частью первичного ключа таблицы или неключевой колонкой. Все неключевые колонки, которые следуют за указанной колонкой, размещаются в сегменте переполнения, который определяется ключевым словом .
СУБД Oracle предусмотрено еще несколько параметров индексирования, которые позволяют улучшить традиционные для всех СУБД индексы со структурой B-Tree. К таким модификациям, помимо
Каждый бит так называемого битового (bitmap) индекса относится к идентификатору строки ROWID в табличном объекте. Если некоторая строка содержит данное ключевое значение, то в индексе для этого значения сохраняется единица. Такая организация индекса может в некоторых случаях значительно повысить производительность выборки данных, т.к. для извлечения строк с определенным значением индекса СУБД нужно лишь найти все единицы, отвечающие ключу. Физически такой индекс организован на основе структуры B-Tree, но задача сводится к поиску данной строки за счет одной операции чтения битовой индексной структуры. Этот тип индекса очень эффективен для индексирования колонок с небольшим кардинальным числом - пол, цвет и т.д. Если значений у колонки буде много, то объем ввода/вывода будет возрастать.
Пример. Для нашей учебной базы данных можно построить
битовый индекс для таблицыEMPLOYEEпо колонкеDEPNO, как показано ниже:
CREATE BITMAP INDEX emp_ndx ON EMPLOYEE (DEPNO);
В REVERSE к битовым индексам и
Пример. В нашей учебной базе данных числовые ключи, содержащие последовательные числа, есть, в частности, в таблице
PLOYEE - EMPNO. Мы можем определить для этой таблиц дополнительныйиндекс с обращением ключа для извлечения записи о сотруднике. Заметим, что для этой колонки уже естьиндекс первичного ключа .
CREATE INDEX dep_ndx ON EMPLOYEE (EMPNO) REVERSE;
В процессе эксплуатации ALTER INDEX, как показано ниже
ALTER INDEX EMPLOYEE REBUILD NOREVERSE;
Если в предложении WHERE используется функция по индексированной колонке, то обычно СУБД не применяют этот индекс при организации доступа к строкам таблицы. Но при WHERE, то СУБД использует такой индекс для считывания строк, удовлетворяющих
Пример. Обратимся к нашей учебной базе. Предположим, что при поиске сотрудников по фамилии таковая вводится на верхнем регистре, как в примере ниже:
SELECT * FROM EMPLOYEE WHERE UPPER(:ENAME) ORDER BY UPPER(:ENAME);
Тогда, даже при наличии индекса по колонке ENAME, СУБД будет сканировать таблицу, не обращаясь к этому индексу. Проектировщик базы данных, учитывая, что частота таких транзакций будет очень высокой, может предусмотреть создание индекса на основе значений функции от колонки EMANE, как показано ниже:
CREATE INDEX emp_ndx_e ON EMPLOYEE UPPER(:ENAME);
При наличии в базе данных такого индекса СУБД Oracle будет его использовать при обработке вышеприведенного запроса.
Когда проектировщик базы данных приступает к проектированию индексов, то он должен иметь некоторый способ оценки качества создаваемого индекса. Введем несколько понятий, с помощью которых проектировщик может грубо оценить качество потенциального индекса.
EMPLOYEE мы заводим колонку для указания пола - SEX, то кардинальность этой колонки есть 2, так как в природе у людей существует только два пола - мужской и женский. Для колонки первичного ключа кардинальность будет равна числу строк в таблице.
Причиной, по которой кардинальность колонки важна для проектирования индексов, состоит в том, что кардинальность индексируемой колонки определяет число уникальных входов, которые должны сохраняться в индексе, т.е. число записей в индексе. Так, для индексируемой колонки SEX будет существовать два уникальных входа, которые будут повторяться много раз в индексе. При предположении равновероятного распределения пола сотрудников на 100000 строк в таблице EMPLOYEE каждый вход индекса будет повторяться 50000 раз. СУБД вряд ли будут принимать решение об использовании такого индекса при построении плана запроса.
Определить кардинальность потенциальной колонки индексирования в существующей базе данных достаточно просто:
SELECT COUNT (DISTINCT колонка) FROM таблица
При проектировании новой базы данных проектировщик должен оценить кардинальность всех потенциальных индексируемых колонок во всех таблицах базы данных, исходя из имеющейся документации.
Способ, с помощью которого СУБД оценивает действие кардинальности, состоит в использовании
Фактор
В заключение раздела мы приведем список правил для определения колонок, которые являются хорошими и плохими кандидатами для индексирования. Эти правила могут быть использованы проектировщиком базы данных при принятии решения о построении индексов реляционной базы данных.
Хорошими кандидатами для индексирования обычно являются:
Факторы, влияющие на низкую эффективность индексов:
Плохими кандидатами для индексирования обычно являются:
Принимая решение об индексировании, проектировщику базы данных следует соблюдать следующие общие правила при
PRIMARY KEY.К сожалению, часто проектировщики принимают крайне неудачные решения об индексировании. Это приводит к тому, что в базе данных появляется слишком много индексов. В результате тратится много времени на поддержку этих индексов, дисковое пространство расходуется неэффективно, СУБД "путается" в выборе подходящего индекса или не использует их вовсе. Проектировщик базы данных должен помнить, что есть две главные причины построить индекс:
Во многих базах данных в таблицах хранится огромное количество данных. Чем больше размер таблицы, тем больше времени потребуется как для некоторых операций по выборке строк таблицы, так и для выполнения некоторых функций
В осуществлении
В СУБД Oracle поддерживается несколько видов
CREATE TABLE с предложением PARTITION. В СУБД Oracle ключ LONG.
(рис 11.2) Пример секционирования подиапазону
Пример. Рассмотрим систему обработки заказов. Предположим, что в ней есть таблица
Sales, в которой сохраняются данных о количестве, времени и цене продаж для каждого клиента. Проектировщик базы данных может использоватьсекционирование по диапазону, а именно - по кварталу, для представления этой таблицы в базе данных. Предположим, что мы имеем четыре определенные ранее табличных пространства c именамиts_01, ts_02, ts_03, ts_04, распределенные по четырем дискам, как показано на рисунке ниже.
Фрагмент скрипта ниже определяет таблицу Sales с физическим размещением секций, как на рисунке выше:
CREATE TABLE Sales
(
s_customer_id number(6),
s_amt number(9,2),
s_date date)
PARTITION BY RANGE (s_date)
(PARTITION st_q01 VALUES LESS THAN ('01-apr-2002')
TABLESPACE ts_01,
PARTITION st_q02 VALUES LESS THAN ('01-jul-2002')
TABLESPACE ts_02,
PARTITION st_q03 VALUES LESS THAN ('01-oct-2002')
TABLESPACE ts_03,
PARTITION st_q04 VALUES LESS THAN (MAXVALUE)
TABLESPACE ts_04
);
Предложение PARTITION BY RANGE (s_date) указывает СУБД Oracle выполнить s_date. Предложения вида (PARTITION st_q01 VALUES LESS THAN ('01- определяют имя секции st_q01 и ее размещение в соответствующем ts_01.
Чтобы получить доступ к строкам таблицы, расположенным в определенной секции, узнать о продажах в третьем квартале, можно использовать команду SELECT, как показано ниже:
SELECT s_customer_id, s_amt FROM Sales PARTITION (st_q03);
Как мы можем увидеть, для этого нужно указать опцию PARTITION (имя секции) после имени таблицы в предложении FROM.
. Удалить отдельную секцию можно также, удалив соответствующее ей
Пример. Рассмотрим ту же таблицу
Sales, что и в предыдущем примере, и ту же схему (рис. 11.2) табличных пространств. Однако используем в качествеключа секционирования идентификацию клиента. Отметим, что распределение значений этой колонки может быть очень неравномерно. Фрагмент кода SQL для создания хэш-секционированной таблицы Sales можно написать так:
CREATE TABLE Sales ( s_customer_id number(6), s_amt number(9,2), s_date date) PARTITION BY HASH (s_customer_id) (PARTITION q01 TABLESPACE ts_01, PARTITION q02 TABLESPACE ts_02, PARTITION q03 TABLESPACE ts_03, PARTITION q04 TABLESPACE ts_04 );
Предложение PARTITION BY HASH (s_customer_id) указывает СУБД Oracle выполнить s_customer_id. Предложения вида (PARTITION q01 определяют имя секции st_q01 и ее размещение в соответствующем ts_01.
Пример. Рассмотрим ту же, что и в предыдущем примере таблицу
Salesи ту же схему (рис. 11.2) табличных пространств. В качествеключа секционирования по диапазону используем дату продажи. В качестве ключа хэш-секционирования -идентификацию клиента. Однако теперь каждая секция по диапазону будет разделена на предопределенное число подсекций. Фрагмент кода SQL для создания таблицыSalesс составным секционированием можно написать так:
CREATE TABLE Sales
(
s_customer_id number(6),
s_amt number(9,2),
s_date date)
PARTITION BY RANGE (s_date)
SUB PARTITION BY HASH (s_customer_id)
SUB PARTITION 4
STORE IN (ts_01, ts_02, ts_03, ts_04)
(PARTITION q01 VALUES LESS THAN ('01-apr-2002'),
PARTITION q02 VALUES LESS THAN ('01-jul-2002'),
PARTITION q03 VALUES LESS THAN ('01-oct-2002'),
PARTITION q04 VALUES LESS THAN (MAXVALUE)
);
Секции q01, q02, q03, q04 будут содержать строки с диапазоном дат, которые определены в предложениях типа PARTITION q02 VALUES LESS THAN ('01-jul-2002') и будут распределены в табличных пространствах ts_01, ts_02, ts_03, ts_04. Предложение SUB PARTITION 4 предписывает СУБД Oracle разбиение каждой секции на четыре логические единицы, а предложение SUB PARTITION BY HASH (s_customer_id) распределяет строки заданного диапазона среди этих четырех подчиненных секций.
В СУБД Oracle предусмотрено PARTITION BY RANGE, в котором задаются параметры
Индексы могут быть секционированы и в случае, когда индексируемая таблица не секционируется. В этом случае по умолчанию предполагается, что индекс является глобальным
В локально
Пример. Создадим локальный секционированный индекс для таблицы Sales (рис. 11.2). Ключом
секционирования этой таблицы является колонкаs_date. Фрагмент кода создания индекса приведен ниже.
CREATE INDEX sales_ndx ON Sales (s_date) LOCAL (PARTITION st_i_q01 TABLESPACE ts_01, PARTITION st_i_q02 TABLESPACE ts_02, PARTITION st_i_q03 TABLESPACE ts_03, PARTITION st_i_q04 TABLESPACE ts_04 );
Локально секционированный индекс называется равносекционированным (equi-partitioned), если он имеет то же число секций и те же правила PARTITION BY RANGE. Oracle автоматически берет структуру Sales. Также можно опустить и предложения типа PARTITION st_i_q02 . Если опущено PARTITION, то Oracle автоматически создаст имена секций. Если опущено , то Oracle автоматически разместит секции в тех же табличных пространствах, в которых находятся соответствующие секции
Глобально секционированный индекс имеет структуру секций, отличную от структуры секций Sales из наших предыдущих примеров.
Пример. В качестве
ключа секционирования для индекса используем колонкуs_customer_id. Во фрагменте кода ниже для секций индекса используются другие индексные пространстваts_i_01, ts_i_02, ts_i_03. Число секций индекса не совпадает с числом секцийбазовой таблицы для этого индекса:
CREATE INDEX sales_ndx ON Sales (s_customer_id)
GLOBAL
PARTITION BY RANGE (s_customer_id)
(PARTITION st_i_q1 VALUES LESS THAN (10000)
TABLESPACE ts_i_01,
PARTITION st_i_q2 VALUES LESS THAN (20000)
TABLESPACE ts_i_02,
PARTITION st_i_q3 VALUES LESS THAN (MAXVALUE)
TABLESPACE ts_i_03,
);
Локально секционированный индекс может быть создан по колонке, отличной от Sales.
Пример. В качестве колонки
секционирования для индекса выбрана колонкаs_customer_id, а для секций индекса выбраны другие табличные пространстваts_i_01, ts_i_02, ts_i_03, ts_i_04, чем для секцийбазовой таблицы индекса.
CREATE INDEX sales_ndx_1 ON Sales (s_customer_id) LOCAL (PARTITION st_i_q01 TABLESPACE ts_i_01, PARTITION st_i_q02 TABLESPACE ts_i_02, PARTITION st_i_q03 TABLESPACE ts_i_03, PARTITION st_i_q04 TABLESPACE ts_i_04 );
При принятии решения о секционировании индексов проектировщик базы данных должен иметь в виду следующее:
В Oracle есть возможность секционировать представления. Основная идея
Секции представления могут быть определены предикатами CHECK, либо с использованием предложения WHERE. Покажем, как могут быть применены оба приема на примере несколько модифицированной таблицы Sales, которую мы рассматривали в предыдущем разделе. Допустим, что данные о продажах для календарного года размещаются в четырех отдельных таблицах, каждая из которых соответствует кварталу года - Q1_Sales, Q2_Sales, Q3_Sales и Q4_Sales.
Пример.
Секционирование представлений с помощью ограниченияCHECK. С помощью командымы можем добавить ограничения на колонкуALTER TABLE s_dateкаждой таблицы, чтобы ее строки соответствовали одному из кварталов года. Созданное затем представлениеsalesдает возможность обращаться к этим таблицам - как к одной, так и по отдельности:
ALTER TABLE Q1_Sales ADD CONSTRAINT C0 CHECK (s_date BETWEEN 'jan-1-2002' AND 'mar-31-2002'); ALTER TABLE Q2_Sales ADD CONSTRAINT C1 CHECK (s_date BETWEEN 'apr 1-2002' AND 'jun-30-2002'); ALTER TABLE Q3_Sales ADD CONSTRAINT C2 check (s_date BETWEEN 'jul-1-2002' AND 'sep-30-2002'); ALTER TABLE Q4_Sales ADD CONSTRAINT C3 check (s_date BETWEEN 'oct-1-2002' AND 'dec-31-2002'); CREATE VIEW sales_v AS SELECT * FROM Q1_Sales UNION ALL SELECT * FROM Q2_Sales UNION ALL SELECT * FROM Q3_Sales UNION ALL SELECT * FROM Q4_Sales;
Преимуществом такого CHECK не оценивается для каждой строки запроса. Такие предикаты исключают вставку в таблицы строк, не соответствующих критерию предиката. Строки, соответствующие предикату
Пример.
Секционирование представлений с помощью предложенияWHERE. Создадим представление для тех же таблиц, что и в примере выше:
CREATE VIEW sales_v AS SELECT * FROM Q1_Sales WHERE s_date BETWEEN 'jan-1-2002' AND 'mar-31-2002' UNION ALL SELECT * FROM Q2_Sales WHERE s_date BETWEEN 'apr-1-2002' AND 'jun-30-2002' UNION ALL SELECT * FROM Q3_Sales WHERE s_date BETWEEN 'jul-1-2002' AND 'sep-30-2002' UNION ALL SELECT * FROM Q4_Sales WHERE s_date BETWEEN 'oct-1-2002' AND 'dec-31-2002';
Второй метод имеет некоторые недостатки. Во-первых, критерий
У этого приема есть и достоинство по сравнению с использованием ограничения CHECK. Вы можете разместить секцию, соответствующую предикату WHERE, на удаленной базе данных. Фрагмент определения преставления приведен ниже:
SELECT * FROM east_sales@icp.ac.ru WHERE LOC = 'EAST' UNION ALL SELECT * FROM west_sales@ioc.ac.ru WHERE LOC = 'WEST';
Проектировщик базы данных при принятии решения о создании
DML, таким, как загрузка данных, В этом разделе мы рассмотрели некоторые приемы увеличения производительности обработки транзакций, основанные на секционировании объектов реляционной базы данных -
Самой медленной операцией, выполняемой СУБД, является операция чтения данных с диска или запись данных на диск. Если существует возможность уменьшить в несколько раз число таких операций, то общая производительность базы данных может заметно увеличиться.
Следует помнить, что СУБД считывает с диска или записывает на диск за один раз одну физическую страницу данных, размер которой колеблется в зависимости от аппаратной платформы от 512 байт до 4 Кб. Таким образом, если можно физически хранить данные, к которым часто происходит совместное обращение, на одной и той же странице диска или на страницах, физически близко расположенных друг к другу, то скорость доступа к этим данным повышается.
На практике
Пример. Рассмотрим таблицы
DEPARTAMENT и EMPLOYEEнашей учебной базы данных. Они некластеризованы и хранятся каждая на своихфизических страницах . Предположим, что анализ запросов показывает, что в 80% запросов эти таблицы используются совместно, при этом соединение выполняется по колонке DEPNO. Проектировщик базы данных может решить построить кластер для этих двух таблиц. На рисунке ниже показана концептуальная сторона такого решения.
До кластеризации строки из таблиц сохраняются отдельно в своих физических областях на диске.
|
|||
DEPNO |
DNAME |
|
… |
| 10 | Торговля | Москва | |
| 20 | Консалтинг | Черноголовка | |
EMPLOYEE |
|||
EMPNO |
ENAME |
LNAME |
DEPNO |
| 996 | Козырев | Сергей | 10 |
| 997 | Сапегин | Алексей | 20 |
После кластеризации по колонке DEPNO строки таблиц будут сохраняться совместно, разделяя одни и те же
CLUSTER |
||||
DEPNO |
||||
| 10 | DNAME |
|
… | |
| Торговля | Москва | … | ||
| … | … | … | ||
EMPNO |
ENAME |
LNAME |
… | |
| 996 | Козырев | Сергей | … | |
| … | … | … | ||
| 20 | DNAME |
|
… | |
| Консалтинг | Черноголовка | … | ||
EMPNO |
ENAME |
LNAME |
… | |
| 997 | Сапегин | Алексей | … | |
| … | … | … | … | |
Из примера видно, что при соединении таблиц число операций ввода/вывода при доступе к кластеру будет меньше. Также видно, что значение
В силу вышеперечисленных обстоятельств кластеры не рекомендуется создавать для таблиц с интенсивным обновлением данных. Для того чтобы таблица была хорошим кандидатом для ее кластеризации, должны выполняться по крайней мере следующие условия:
Из этого следует, что существуют две основные причины использования кластеров: это необходимость а) обеспечить прямой доступ к строке за одну операцию чтения; и б) сократить число операций ввода/вывода при доступе к часто совместно используемым данным путем размещения их в близко расположенных
С физической точки зрения кластер находится отдельно от таблиц. Он создается с указанием параметров хранения, а затем в нем последовательно создаются кластеризованные таблицы. При описании кластера нужно указать колонки или колонку, для которых СУБД сформирует кластер, и таблицы, которые будут включены в его состав. При обработке данных СУБД будет размещать строки, содержащие одинаковые значения в колонках кластера, физически максимально близко. В результате строки таблицы могут быть распределены среди нескольких дисковых страниц, но первичные и внешние ключи обычно располагаются на одной странице.
Пример. Вернемся к нашей учебной базе данных и напишем фрагмент скрипта для создания кластера для таблиц
DEPARTAMENTиEMPLOYEE. Для создания кластеров используется команда SQLCREATE CLUSTER, которая в нашем случае будет иметь вид
CREATE CLUSTER emp_dept_c (DEPNO integer) SIZE 512, -- TABLESPACE ѕ -- STORAGE ѕ INDEX; CREATE TABLE DEPARTAMENT ( DEPNO integer NOT NULL, DNAME char(20), LOC char(20), MANAGER char(20), PHONE char(15), CLUSTER emp_dept_c (DEPNO) ); CREATE TABLE EMPLOYEE ( EMPNO integer NOT NULL, ENAME char(25), LNAME char(10), DEPNO int NOT NULL,, SSECNO char(10), JOB char(25), AGE date, HIREDATE date NOT NULL WITH DEFAULT, SAL dec(9,2), COMM dec(9,2), FINE dec(9,2), PRIMARY KEY (EMPNO), CLUSTER emp_dept_c (DEPNO) ); CREATE INDEX emp_dept_c_id ON CLUSTER emp_dept_c;
Назначение и смысл закомментированных предложений команды CREATE мы будем обсуждать в следующей главе в отдельном разделе. Они приведены здесь для полноты изложения. Параметр SIZE определяет INDEX означает, что создаваемый кластер является индексным.
Предложение CLUSTER emp_dept_c (DEPNO) указывает СУБД, что таблица должна быть добавлена в кластер. Обратите внимание, что в таблице DEPARTAMENT снято DEPNO. Это связано с тем, что Oracle автоматически создает индекс на первичный ключ, а этот индекс в данном случае не нужен. Последнее предложение создает
В одном из предыдущих разделов мы уже обсуждали вопрос использования
Напомним, что хэширование является способом хранения таблиц данных для увеличения производительности выборки. Физическим механизмом реализации хэширования в СУБД Oracle является
Пример. Рассмотрим нашу учебную базу данных с целью создания
хэш-кластера для таблицыEMPLOYEE. На рис. 11.3 ниже показано, как будет выполняться доступ к записям таблицы до и после кластеризации.
(рис 11.3) Доступк строке таблицы EMPLOYEE через индекс по колонке EPMNO
SELECT * FROM EMPLOYEE WHERE EMPNO= 997;
До кластеризации по колонке EPMNO доступ будет выполняться через индекс, и согласно рисунку 11.3 потребуется 4 операции ввода/вывода, чтобы получить результирующую строку.
После кластеризации по колонке EPMNO строки таблицы EMPLOYEE будут сохраняться в структуре, которая условно приведена на рисунке ниже. После хэширования ключа потребуется одна операция ввода/вывода, чтобы получить результирующую строку, если нет цепочек переполнения.
| CLUSTER | ||||
| Хэш-ключ | ||||
| 110 | EMPNO |
ENAME |
LNAME |
… |
| 996 | Козырев | Сергей | … | |
| … | … | … | ||
| 120 | EMPNO |
ENAME |
LNAME |
… |
| 997 | Сапегин | Алексей | … | |
В CREATE INDEX для
Пример. Создадим
хэш-кластер для таблицыEMPLOYEEнашей учебной базы данных. Фрагмент скрипта приведен ниже.
CREATE CLUSTER PERSONNEL (EMPNO integer) SIZE 512 HASHKEYS 500 -- STORAGE (INITIAL 100K NEXT 50K PCTINCREASE 10) ;
Число уникальных значений хэш-ключа задается параметром HASHKEYS, после достижения этого значения в таблицы будут возникать коллизии - ситуации, когда разные хэшированные ключи должны будут размещаться в одном блоке. Это приводит к созданию при вставке строк так называемых цепочек переполнения, из-за которых увеличивается число доступов при выборке результирующей строки.
Параметр SIZE определяет максимальное число хэш-ключей, размещаемое на
С помощью предложения HASH IS вы можете переопределить
Пример. Если у нас есть
хэш-кластер для таблицыEMPLOYEEикластерный ключ определен как код домашнего адреса сотрудника, то вероятно, что будет случаться много коллизий вхэш-кластере , если городок, где живут сотрудники, невелик. Для того чтобы избежать такой коллизии, можно переопределить встроеннуюхэш-функцию Oracle в командеCREATE CLUSTER, добавив предложениеHASH IS, как показано ниже.
CREATE CLUSTER personnel (home_area_code number, home_prefix number ) HASHKEYS 20 HASH IS MOD(home_area_code + home_suffix_tel, 101);
В примере добавлено некоторое число к коду домашнего адреса, чтобы изменить распределение значений хэш-ключа с целью избежать коллизий. В качестве такого числа взяты две последние цифры домашнего телефона.
В заключение отметим следующее. Несмотря на то, что СУБД Oracle, так же как и СУБД SQLBase, интенсивно использует кластеры для доступа к системным таблицам базы данных, автор настоящего курса рекомендует проектировщикам базы данных проявлять осторожность при принятии решения о кластеризации таблиц при создании новой базы данных. Выигрыш в производительности может быть не слишком высок по сравнению с другими проектными решениями. Проектирование кластеров - штучная работа. Очень полезно знать статистику использования аналогичного кластера при эксплуатации аналогичной базы данных, чтобы построить высокопроизводительный кластер. Придерживайтесь следующих эмпирических правил:
Как уже отмечалось в предыдущей лекции, одна из важнейших задач физического
О
Концептуально действие индекса состоит в следующем. В индексе содержится упорядоченный список значений колонки или комбинации колонок, а также сведения о местонахождении на жестком диске соответствующих этим значениям строк таблицы. Значения колонки в индексе упорядочены. Несмотря на то, что порядок строк в таблице случаен, индекс можно быстро просмотреть, чтобы найти конкретное значение. Упорядоченный индекс можно просмотреть во много раз быстрее, чем неупорядоченную таблицу. Чем выше степень различия значений ключа в колонке, тем быстрее будет выполняться доступ к строкам этой таблицы.
Так при вставке новой записи в таблицу проверка уникальности первичного ключа реализуется не реальным просмотром индекса, а тем, что требование уникальности предъявляется к значениям колонки первичного ключа в индексе. Таким образом, индекс - это объект базы данных, который может существенно сократить время поиска нужных строк в таблице.
Замечание. После того как вы создали индекс, оптимизатор СУБД, о котором пойдет речь в последней лекции, будет использовать его всякий раз, когда это ускоряет считывание данных. Обратите внимание на то, что созданный вами индекс может ни разу не использоваться!
Индексы, несомненно, занимают место в базе данных. При вводе новых данных или удалении данных СУБД приходится обновлять и таблицы, и индексы. Это может замедлить выполнение операций модификации данных, особенно для таблиц с большим числом строк. Таким образом, может возникнуть проблема, суть которой состоит в возникновении конфликта между скоростью обновления данных в таблице и скоростью ее считываний. При разрешении этой проблемы следует придерживаться следующего эмпирического правила: создавайте индексы для колонок первичных ключей и других колонок, часто используемых в тех запросах, в которых для выборки данных применяются логические критерии. Если в результате скорость обновления данных ухудшается, то можно рассмотреть вопрос об удалении некоторых индексов.
Каждая таблица базы данных может иметь один или несколько индексов. Индексы могут создаваться по одной колонке или нескольким колонкам таблицы. Колонки, входящие в индекс, принято называть
В СУБД Oracle и SQLBase каждая строка таблицы обладает уникальным идентификатором ROWID - идентификатором строки, который представляет собой псевдоколонку с информацией о точном расположении строки в базе данных и содержит еще некоторую идентифицирующую информацию (
Зачем создавать индекс для колонки или группы колонок? Это важный вопрос, и мы на него можем ответить следующим образом:
На этапе физического
Чтобы решать эти задачи, проектировщик базы данных должен знать, как работает индекс, какие типы индексов поддерживает СУБД, а также понимать смысл методов индексирования.
Сначала мы опишем типы индексов вместе с методами индексирования для каждого типа, затем разберем вопрос о том, как работает индекс, и в заключение дадим некоторые рекомендации по созданию и использованию индексов.
Индекс на основе сбалансированной иерархической структуры, или индекс B-Tree (Balanced
(рис 11.1) Концептуальная организация B-Tree индекса
Замечание. Следует отметить два случая, когда после выборки идентификатора строки из индекса может понадобиться несколько посещений
физической страницы индекса: 1) когда строка имеет длину более однойфизической страницы , так называемая расщепленная строка; 2) когда строка за время своего существования в базе данных увеличилась и была перемещена из исходной страницы в другую, так называемая мигрировавшая строка.
Индекс B-Tree характеризуется количеством уровней в индексе (height). Чем меньше уровней, тем выше производительность.
Индекс B-Tree - это физический объект реляционной базы данных, организованный по принципу сбалансированной иерархической структуры и обладающий набором свойств. Сформулируем некоторые свойства индексов со структурой B-Tree.
ORDER BY в запросе.{Ename, Job} для обработки запросаSELECT * FROM EMPLOYEE WHERE Job='Инженер';применяться не будет.
NULL не индексируются. Если для таких колонок строится индекс, то СУБД будет отказываться примерять его в некоторых операциях, например ORDER BY.Индексы создаются командой SQL CREATE INDEX. В предыдущих лекциях мы уже создавали индексы на основе B-Tree. При
Пример. В нашей учебной базе создадим для таблицы
EMPLOYEEсоставной индекс по колонкамEname и Job. При этом проектировщик базы данных не уверен, что этот индекс будет использоваться эффективно, поэтому он задал опцию для сбора статистики для этого индекса.
CREATE INDEX emp_ndx2 ON EMPLOYEE (Ename, Job) COMPUTE STATISTICS;
В этом подразделе мы рассмотрели наиболее часто используемый тип индексов. В последующих подразделах и разделах мы рассмотрим другие типы индексов реляционных баз данных.
Индексы могут создаваться на основе значений одной или нескольких колонок. Если требования к данным в запросе удовлетворяются на основе информации из связанного с этими данными индекса, то доступ к CREATE TABLE, как показано в примере ниже.
Пример. Предположим, что в нашей учебной базе требуется в отдельной таблице сохранять и отслеживать проблемы, возникающие по выполнении всех проектов, и частоту возникновения проблемы. Создадим
исключительно индексную таблицу для этой таблицы, как показано ниже:
CREATE TABLE Proj_Index
( projno char(8) NOT NULL,
t_person char(32) NOT NULL,
t_frequency integer,
t_problem varchar2(512),
CONSTRAINT pk_ndx PRIMARY KEY( projno, t_person) )
ORGANIZATION INDEX
TABLESPACE ts_ndx1
PCTTHRESHOLD 20
INCLUDING t_frequency
OVERFLOW TABLESPACE ts__of_ndx1;
Команда CREATE TABLE не отличается ничем от других команд создания таблиц до тех пор, пока не встретится предложение ORGANIZATION INDEX, которое указывает СУБД на создание PCTTHRESHOLD указывает, что оставшуюся часть строки нужно сохранять в заданном INCLUDING определяет имя колонки, с которой строка индексной таблицы делится на две части: индексную и переполнения. Эта колонка может быть частью первичного ключа таблицы или неключевой колонкой. Все неключевые колонки, которые следуют за указанной колонкой, размещаются в сегменте переполнения, который определяется ключевым словом .
СУБД Oracle предусмотрено еще несколько параметров индексирования, которые позволяют улучшить традиционные для всех СУБД индексы со структурой B-Tree. К таким модификациям, помимо
Каждый бит так называемого битового (bitmap) индекса относится к идентификатору строки ROWID в табличном объекте. Если некоторая строка содержит данное ключевое значение, то в индексе для этого значения сохраняется единица. Такая организация индекса может в некоторых случаях значительно повысить производительность выборки данных, т.к. для извлечения строк с определенным значением индекса СУБД нужно лишь найти все единицы, отвечающие ключу. Физически такой индекс организован на основе структуры B-Tree, но задача сводится к поиску данной строки за счет одной операции чтения битовой индексной структуры. Этот тип индекса очень эффективен для индексирования колонок с небольшим кардинальным числом - пол, цвет и т.д. Если значений у колонки буде много, то объем ввода/вывода будет возрастать.
Пример. Для нашей учебной базы данных можно построить
битовый индекс для таблицыEMPLOYEEпо колонкеDEPNO, как показано ниже:
CREATE BITMAP INDEX emp_ndx ON EMPLOYEE (DEPNO);
В REVERSE к битовым индексам и
Пример. В нашей учебной базе данных числовые ключи, содержащие последовательные числа, есть, в частности, в таблице
PLOYEE - EMPNO. Мы можем определить для этой таблиц дополнительныйиндекс с обращением ключа для извлечения записи о сотруднике. Заметим, что для этой колонки уже естьиндекс первичного ключа .
CREATE INDEX dep_ndx ON EMPLOYEE (EMPNO) REVERSE;
В процессе эксплуатации ALTER INDEX, как показано ниже
ALTER INDEX EMPLOYEE REBUILD NOREVERSE;
Если в предложении WHERE используется функция по индексированной колонке, то обычно СУБД не применяют этот индекс при организации доступа к строкам таблицы. Но при WHERE, то СУБД использует такой индекс для считывания строк, удовлетворяющих
Пример. Обратимся к нашей учебной базе. Предположим, что при поиске сотрудников по фамилии таковая вводится на верхнем регистре, как в примере ниже:
SELECT * FROM EMPLOYEE WHERE UPPER(:ENAME) ORDER BY UPPER(:ENAME);
Тогда, даже при наличии индекса по колонке ENAME, СУБД будет сканировать таблицу, не обращаясь к этому индексу. Проектировщик базы данных, учитывая, что частота таких транзакций будет очень высокой, может предусмотреть создание индекса на основе значений функции от колонки EMANE, как показано ниже:
CREATE INDEX emp_ndx_e ON EMPLOYEE UPPER(:ENAME);
При наличии в базе данных такого индекса СУБД Oracle будет его использовать при обработке вышеприведенного запроса.
Когда проектировщик базы данных приступает к проектированию индексов, то он должен иметь некоторый способ оценки качества создаваемого индекса. Введем несколько понятий, с помощью которых проектировщик может грубо оценить качество потенциального индекса.
EMPLOYEE мы заводим колонку для указания пола - SEX, то кардинальность этой колонки есть 2, так как в природе у людей существует только два пола - мужской и женский. Для колонки первичного ключа кардинальность будет равна числу строк в таблице.
Причиной, по которой кардинальность колонки важна для проектирования индексов, состоит в том, что кардинальность индексируемой колонки определяет число уникальных входов, которые должны сохраняться в индексе, т.е. число записей в индексе. Так, для индексируемой колонки SEX будет существовать два уникальных входа, которые будут повторяться много раз в индексе. При предположении равновероятного распределения пола сотрудников на 100000 строк в таблице EMPLOYEE каждый вход индекса будет повторяться 50000 раз. СУБД вряд ли будут принимать решение об использовании такого индекса при построении плана запроса.
Определить кардинальность потенциальной колонки индексирования в существующей базе данных достаточно просто:
SELECT COUNT (DISTINCT колонка) FROM таблица
При проектировании новой базы данных проектировщик должен оценить кардинальность всех потенциальных индексируемых колонок во всех таблицах базы данных, исходя из имеющейся документации.
Способ, с помощью которого СУБД оценивает действие кардинальности, состоит в использовании
Фактор
В заключение раздела мы приведем список правил для определения колонок, которые являются хорошими и плохими кандидатами для индексирования. Эти правила могут быть использованы проектировщиком базы данных при принятии решения о построении индексов реляционной базы данных.
Хорошими кандидатами для индексирования обычно являются:
Факторы, влияющие на низкую эффективность индексов:
Плохими кандидатами для индексирования обычно являются:
Принимая решение об индексировании, проектировщику базы данных следует соблюдать следующие общие правила при
PRIMARY KEY.К сожалению, часто проектировщики принимают крайне неудачные решения об индексировании. Это приводит к тому, что в базе данных появляется слишком много индексов. В результате тратится много времени на поддержку этих индексов, дисковое пространство расходуется неэффективно, СУБД "путается" в выборе подходящего индекса или не использует их вовсе. Проектировщик базы данных должен помнить, что есть две главные причины построить индекс:
Во многих базах данных в таблицах хранится огромное количество данных. Чем больше размер таблицы, тем больше времени потребуется как для некоторых операций по выборке строк таблицы, так и для выполнения некоторых функций
В осуществлении
В СУБД Oracle поддерживается несколько видов
CREATE TABLE с предложением PARTITION. В СУБД Oracle ключ LONG.
(рис 11.2) Пример секционирования подиапазону
Пример. Рассмотрим систему обработки заказов. Предположим, что в ней есть таблица
Sales, в которой сохраняются данных о количестве, времени и цене продаж для каждого клиента. Проектировщик базы данных может использоватьсекционирование по диапазону, а именно - по кварталу, для представления этой таблицы в базе данных. Предположим, что мы имеем четыре определенные ранее табличных пространства c именамиts_01, ts_02, ts_03, ts_04, распределенные по четырем дискам, как показано на рисунке ниже.
Фрагмент скрипта ниже определяет таблицу Sales с физическим размещением секций, как на рисунке выше:
CREATE TABLE Sales
(
s_customer_id number(6),
s_amt number(9,2),
s_date date)
PARTITION BY RANGE (s_date)
(PARTITION st_q01 VALUES LESS THAN ('01-apr-2002')
TABLESPACE ts_01,
PARTITION st_q02 VALUES LESS THAN ('01-jul-2002')
TABLESPACE ts_02,
PARTITION st_q03 VALUES LESS THAN ('01-oct-2002')
TABLESPACE ts_03,
PARTITION st_q04 VALUES LESS THAN (MAXVALUE)
TABLESPACE ts_04
);
Предложение PARTITION BY RANGE (s_date) указывает СУБД Oracle выполнить s_date. Предложения вида (PARTITION st_q01 VALUES LESS THAN ('01- определяют имя секции st_q01 и ее размещение в соответствующем ts_01.
Чтобы получить доступ к строкам таблицы, расположенным в определенной секции, узнать о продажах в третьем квартале, можно использовать команду SELECT, как показано ниже:
SELECT s_customer_id, s_amt FROM Sales PARTITION (st_q03);
Как мы можем увидеть, для этого нужно указать опцию PARTITION (имя секции) после имени таблицы в предложении FROM.
. Удалить отдельную секцию можно также, удалив соответствующее ей
Пример. Рассмотрим ту же таблицу
Sales, что и в предыдущем примере, и ту же схему (рис. 11.2) табличных пространств. Однако используем в качествеключа секционирования идентификацию клиента. Отметим, что распределение значений этой колонки может быть очень неравномерно. Фрагмент кода SQL для создания хэш-секционированной таблицы Sales можно написать так:
CREATE TABLE Sales ( s_customer_id number(6), s_amt number(9,2), s_date date) PARTITION BY HASH (s_customer_id) (PARTITION q01 TABLESPACE ts_01, PARTITION q02 TABLESPACE ts_02, PARTITION q03 TABLESPACE ts_03, PARTITION q04 TABLESPACE ts_04 );
Предложение PARTITION BY HASH (s_customer_id) указывает СУБД Oracle выполнить s_customer_id. Предложения вида (PARTITION q01 определяют имя секции st_q01 и ее размещение в соответствующем ts_01.
Пример. Рассмотрим ту же, что и в предыдущем примере таблицу
Salesи ту же схему (рис. 11.2) табличных пространств. В качествеключа секционирования по диапазону используем дату продажи. В качестве ключа хэш-секционирования -идентификацию клиента. Однако теперь каждая секция по диапазону будет разделена на предопределенное число подсекций. Фрагмент кода SQL для создания таблицыSalesс составным секционированием можно написать так:
CREATE TABLE Sales
(
s_customer_id number(6),
s_amt number(9,2),
s_date date)
PARTITION BY RANGE (s_date)
SUB PARTITION BY HASH (s_customer_id)
SUB PARTITION 4
STORE IN (ts_01, ts_02, ts_03, ts_04)
(PARTITION q01 VALUES LESS THAN ('01-apr-2002'),
PARTITION q02 VALUES LESS THAN ('01-jul-2002'),
PARTITION q03 VALUES LESS THAN ('01-oct-2002'),
PARTITION q04 VALUES LESS THAN (MAXVALUE)
);
Секции q01, q02, q03, q04 будут содержать строки с диапазоном дат, которые определены в предложениях типа PARTITION q02 VALUES LESS THAN ('01-jul-2002') и будут распределены в табличных пространствах ts_01, ts_02, ts_03, ts_04. Предложение SUB PARTITION 4 предписывает СУБД Oracle разбиение каждой секции на четыре логические единицы, а предложение SUB PARTITION BY HASH (s_customer_id) распределяет строки заданного диапазона среди этих четырех подчиненных секций.
В СУБД Oracle предусмотрено PARTITION BY RANGE, в котором задаются параметры
Индексы могут быть секционированы и в случае, когда индексируемая таблица не секционируется. В этом случае по умолчанию предполагается, что индекс является глобальным
В локально
Пример. Создадим локальный секционированный индекс для таблицы Sales (рис. 11.2). Ключом
секционирования этой таблицы является колонкаs_date. Фрагмент кода создания индекса приведен ниже.
CREATE INDEX sales_ndx ON Sales (s_date) LOCAL (PARTITION st_i_q01 TABLESPACE ts_01, PARTITION st_i_q02 TABLESPACE ts_02, PARTITION st_i_q03 TABLESPACE ts_03, PARTITION st_i_q04 TABLESPACE ts_04 );
Локально секционированный индекс называется равносекционированным (equi-partitioned), если он имеет то же число секций и те же правила PARTITION BY RANGE. Oracle автоматически берет структуру Sales. Также можно опустить и предложения типа PARTITION st_i_q02 . Если опущено PARTITION, то Oracle автоматически создаст имена секций. Если опущено , то Oracle автоматически разместит секции в тех же табличных пространствах, в которых находятся соответствующие секции
Глобально секционированный индекс имеет структуру секций, отличную от структуры секций Sales из наших предыдущих примеров.
Пример. В качестве
ключа секционирования для индекса используем колонкуs_customer_id. Во фрагменте кода ниже для секций индекса используются другие индексные пространстваts_i_01, ts_i_02, ts_i_03. Число секций индекса не совпадает с числом секцийбазовой таблицы для этого индекса:
CREATE INDEX sales_ndx ON Sales (s_customer_id)
GLOBAL
PARTITION BY RANGE (s_customer_id)
(PARTITION st_i_q1 VALUES LESS THAN (10000)
TABLESPACE ts_i_01,
PARTITION st_i_q2 VALUES LESS THAN (20000)
TABLESPACE ts_i_02,
PARTITION st_i_q3 VALUES LESS THAN (MAXVALUE)
TABLESPACE ts_i_03,
);
Локально секционированный индекс может быть создан по колонке, отличной от Sales.
Пример. В качестве колонки
секционирования для индекса выбрана колонкаs_customer_id, а для секций индекса выбраны другие табличные пространстваts_i_01, ts_i_02, ts_i_03, ts_i_04, чем для секцийбазовой таблицы индекса.
CREATE INDEX sales_ndx_1 ON Sales (s_customer_id) LOCAL (PARTITION st_i_q01 TABLESPACE ts_i_01, PARTITION st_i_q02 TABLESPACE ts_i_02, PARTITION st_i_q03 TABLESPACE ts_i_03, PARTITION st_i_q04 TABLESPACE ts_i_04 );
При принятии решения о секционировании индексов проектировщик базы данных должен иметь в виду следующее:
В Oracle есть возможность секционировать представления. Основная идея
Секции представления могут быть определены предикатами CHECK, либо с использованием предложения WHERE. Покажем, как могут быть применены оба приема на примере несколько модифицированной таблицы Sales, которую мы рассматривали в предыдущем разделе. Допустим, что данные о продажах для календарного года размещаются в четырех отдельных таблицах, каждая из которых соответствует кварталу года - Q1_Sales, Q2_Sales, Q3_Sales и Q4_Sales.
Пример.
Секционирование представлений с помощью ограниченияCHECK. С помощью командымы можем добавить ограничения на колонкуALTER TABLE s_dateкаждой таблицы, чтобы ее строки соответствовали одному из кварталов года. Созданное затем представлениеsalesдает возможность обращаться к этим таблицам - как к одной, так и по отдельности:
ALTER TABLE Q1_Sales ADD CONSTRAINT C0 CHECK (s_date BETWEEN 'jan-1-2002' AND 'mar-31-2002'); ALTER TABLE Q2_Sales ADD CONSTRAINT C1 CHECK (s_date BETWEEN 'apr 1-2002' AND 'jun-30-2002'); ALTER TABLE Q3_Sales ADD CONSTRAINT C2 check (s_date BETWEEN 'jul-1-2002' AND 'sep-30-2002'); ALTER TABLE Q4_Sales ADD CONSTRAINT C3 check (s_date BETWEEN 'oct-1-2002' AND 'dec-31-2002'); CREATE VIEW sales_v AS SELECT * FROM Q1_Sales UNION ALL SELECT * FROM Q2_Sales UNION ALL SELECT * FROM Q3_Sales UNION ALL SELECT * FROM Q4_Sales;
Преимуществом такого CHECK не оценивается для каждой строки запроса. Такие предикаты исключают вставку в таблицы строк, не соответствующих критерию предиката. Строки, соответствующие предикату
Пример.
Секционирование представлений с помощью предложенияWHERE. Создадим представление для тех же таблиц, что и в примере выше:
CREATE VIEW sales_v AS SELECT * FROM Q1_Sales WHERE s_date BETWEEN 'jan-1-2002' AND 'mar-31-2002' UNION ALL SELECT * FROM Q2_Sales WHERE s_date BETWEEN 'apr-1-2002' AND 'jun-30-2002' UNION ALL SELECT * FROM Q3_Sales WHERE s_date BETWEEN 'jul-1-2002' AND 'sep-30-2002' UNION ALL SELECT * FROM Q4_Sales WHERE s_date BETWEEN 'oct-1-2002' AND 'dec-31-2002';
Второй метод имеет некоторые недостатки. Во-первых, критерий
У этого приема есть и достоинство по сравнению с использованием ограничения CHECK. Вы можете разместить секцию, соответствующую предикату WHERE, на удаленной базе данных. Фрагмент определения преставления приведен ниже:
SELECT * FROM east_sales@icp.ac.ru WHERE LOC = 'EAST' UNION ALL SELECT * FROM west_sales@ioc.ac.ru WHERE LOC = 'WEST';
Проектировщик базы данных при принятии решения о создании
DML, таким, как загрузка данных, В этом разделе мы рассмотрели некоторые приемы увеличения производительности обработки транзакций, основанные на секционировании объектов реляционной базы данных -
Самой медленной операцией, выполняемой СУБД, является операция чтения данных с диска или запись данных на диск. Если существует возможность уменьшить в несколько раз число таких операций, то общая производительность базы данных может заметно увеличиться.
Следует помнить, что СУБД считывает с диска или записывает на диск за один раз одну физическую страницу данных, размер которой колеблется в зависимости от аппаратной платформы от 512 байт до 4 Кб. Таким образом, если можно физически хранить данные, к которым часто происходит совместное обращение, на одной и той же странице диска или на страницах, физически близко расположенных друг к другу, то скорость доступа к этим данным повышается.
На практике
Пример. Рассмотрим таблицы
DEPARTAMENT и EMPLOYEEнашей учебной базы данных. Они некластеризованы и хранятся каждая на своихфизических страницах . Предположим, что анализ запросов показывает, что в 80% запросов эти таблицы используются совместно, при этом соединение выполняется по колонке DEPNO. Проектировщик базы данных может решить построить кластер для этих двух таблиц. На рисунке ниже показана концептуальная сторона такого решения.
До кластеризации строки из таблиц сохраняются отдельно в своих физических областях на диске.
|
|||
DEPNO |
DNAME |
|
… |
| 10 | Торговля | Москва | |
| 20 | Консалтинг | Черноголовка | |
EMPLOYEE |
|||
EMPNO |
ENAME |
LNAME |
DEPNO |
| 996 | Козырев | Сергей | 10 |
| 997 | Сапегин | Алексей | 20 |
После кластеризации по колонке DEPNO строки таблиц будут сохраняться совместно, разделяя одни и те же
CLUSTER |
||||
DEPNO |
||||
| 10 | DNAME |
|
… | |
| Торговля | Москва | … | ||
| … | … | … | ||
EMPNO |
ENAME |
LNAME |
… | |
| 996 | Козырев | Сергей | … | |
| … | … | … | ||
| 20 | DNAME |
|
… | |
| Консалтинг | Черноголовка | … | ||
EMPNO |
ENAME |
LNAME |
… | |
| 997 | Сапегин | Алексей | … | |
| … | … | … | … | |
Из примера видно, что при соединении таблиц число операций ввода/вывода при доступе к кластеру будет меньше. Также видно, что значение
В силу вышеперечисленных обстоятельств кластеры не рекомендуется создавать для таблиц с интенсивным обновлением данных. Для того чтобы таблица была хорошим кандидатом для ее кластеризации, должны выполняться по крайней мере следующие условия:
Из этого следует, что существуют две основные причины использования кластеров: это необходимость а) обеспечить прямой доступ к строке за одну операцию чтения; и б) сократить число операций ввода/вывода при доступе к часто совместно используемым данным путем размещения их в близко расположенных
С физической точки зрения кластер находится отдельно от таблиц. Он создается с указанием параметров хранения, а затем в нем последовательно создаются кластеризованные таблицы. При описании кластера нужно указать колонки или колонку, для которых СУБД сформирует кластер, и таблицы, которые будут включены в его состав. При обработке данных СУБД будет размещать строки, содержащие одинаковые значения в колонках кластера, физически максимально близко. В результате строки таблицы могут быть распределены среди нескольких дисковых страниц, но первичные и внешние ключи обычно располагаются на одной странице.
Пример. Вернемся к нашей учебной базе данных и напишем фрагмент скрипта для создания кластера для таблиц
DEPARTAMENTиEMPLOYEE. Для создания кластеров используется команда SQLCREATE CLUSTER, которая в нашем случае будет иметь вид
CREATE CLUSTER emp_dept_c (DEPNO integer) SIZE 512, -- TABLESPACE ѕ -- STORAGE ѕ INDEX; CREATE TABLE DEPARTAMENT ( DEPNO integer NOT NULL, DNAME char(20), LOC char(20), MANAGER char(20), PHONE char(15), CLUSTER emp_dept_c (DEPNO) ); CREATE TABLE EMPLOYEE ( EMPNO integer NOT NULL, ENAME char(25), LNAME char(10), DEPNO int NOT NULL,, SSECNO char(10), JOB char(25), AGE date, HIREDATE date NOT NULL WITH DEFAULT, SAL dec(9,2), COMM dec(9,2), FINE dec(9,2), PRIMARY KEY (EMPNO), CLUSTER emp_dept_c (DEPNO) ); CREATE INDEX emp_dept_c_id ON CLUSTER emp_dept_c;
Назначение и смысл закомментированных предложений команды CREATE мы будем обсуждать в следующей главе в отдельном разделе. Они приведены здесь для полноты изложения. Параметр SIZE определяет INDEX означает, что создаваемый кластер является индексным.
Предложение CLUSTER emp_dept_c (DEPNO) указывает СУБД, что таблица должна быть добавлена в кластер. Обратите внимание, что в таблице DEPARTAMENT снято DEPNO. Это связано с тем, что Oracle автоматически создает индекс на первичный ключ, а этот индекс в данном случае не нужен. Последнее предложение создает
В одном из предыдущих разделов мы уже обсуждали вопрос использования
Напомним, что хэширование является способом хранения таблиц данных для увеличения производительности выборки. Физическим механизмом реализации хэширования в СУБД Oracle является
Пример. Рассмотрим нашу учебную базу данных с целью создания
хэш-кластера для таблицыEMPLOYEE. На рис. 11.3 ниже показано, как будет выполняться доступ к записям таблицы до и после кластеризации.
(рис 11.3) Доступк строке таблицы EMPLOYEE через индекс по колонке EPMNO
SELECT * FROM EMPLOYEE WHERE EMPNO= 997;
До кластеризации по колонке EPMNO доступ будет выполняться через индекс, и согласно рисунку 11.3 потребуется 4 операции ввода/вывода, чтобы получить результирующую строку.
После кластеризации по колонке EPMNO строки таблицы EMPLOYEE будут сохраняться в структуре, которая условно приведена на рисунке ниже. После хэширования ключа потребуется одна операция ввода/вывода, чтобы получить результирующую строку, если нет цепочек переполнения.
| CLUSTER | ||||
| Хэш-ключ | ||||
| 110 | EMPNO |
ENAME |
LNAME |
… |
| 996 | Козырев | Сергей | … | |
| … | … | … | ||
| 120 | EMPNO |
ENAME |
LNAME |
… |
| 997 | Сапегин | Алексей | … | |
В CREATE INDEX для
Пример. Создадим
хэш-кластер для таблицыEMPLOYEEнашей учебной базы данных. Фрагмент скрипта приведен ниже.
CREATE CLUSTER PERSONNEL (EMPNO integer) SIZE 512 HASHKEYS 500 -- STORAGE (INITIAL 100K NEXT 50K PCTINCREASE 10) ;
Число уникальных значений хэш-ключа задается параметром HASHKEYS, после достижения этого значения в таблицы будут возникать коллизии - ситуации, когда разные хэшированные ключи должны будут размещаться в одном блоке. Это приводит к созданию при вставке строк так называемых цепочек переполнения, из-за которых увеличивается число доступов при выборке результирующей строки.
Параметр SIZE определяет максимальное число хэш-ключей, размещаемое на
С помощью предложения HASH IS вы можете переопределить
Пример. Если у нас есть
хэш-кластер для таблицыEMPLOYEEикластерный ключ определен как код домашнего адреса сотрудника, то вероятно, что будет случаться много коллизий вхэш-кластере , если городок, где живут сотрудники, невелик. Для того чтобы избежать такой коллизии, можно переопределить встроеннуюхэш-функцию Oracle в командеCREATE CLUSTER, добавив предложениеHASH IS, как показано ниже.
CREATE CLUSTER personnel (home_area_code number, home_prefix number ) HASHKEYS 20 HASH IS MOD(home_area_code + home_suffix_tel, 101);
В примере добавлено некоторое число к коду домашнего адреса, чтобы изменить распределение значений хэш-ключа с целью избежать коллизий. В качестве такого числа взяты две последние цифры домашнего телефона.
В заключение отметим следующее. Несмотря на то, что СУБД Oracle, так же как и СУБД SQLBase, интенсивно использует кластеры для доступа к системным таблицам базы данных, автор настоящего курса рекомендует проектировщикам базы данных проявлять осторожность при принятии решения о кластеризации таблиц при создании новой базы данных. Выигрыш в производительности может быть не слишком высок по сравнению с другими проектными решениями. Проектирование кластеров - штучная работа. Очень полезно знать статистику использования аналогичного кластера при эксплуатации аналогичной базы данных, чтобы построить высокопроизводительный кластер. Придерживайтесь следующих эмпирических правил:
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.