|
Программирование >> Oracle
17 18 19 20 21 22 (x$ename,x$rid) values (upper(:new.ename), :new.rowid); elsif (deleting) then delete from upper ename where x$ename = upper(:old.ename) and x$rid = lold.rowid; end if; end; Trigger created. tkyte@TKYTE816> update emp set ename - initcap(ename); 14 rows updated. tkyte@TKYTE816> commit; Commit complete. Итак, таблица UPPERENAME фактически представляет собой индекс, не зависящий от регистра символов, во многом аналогичный индексу по функции. Этот индекс надо использовать явно - серверу Oracle о нем не известно. Следующие примеры показывают, как можно использовать этот индекс для изменения, выборки и удаления данных из таблицы. tkyte@TKYTE816> update 2 3 4 5 6 7 8 9 10 select ename, from emp where emp.rowid in (select upper ename.x$rid from upper ename where x$ename = KING) 1234 1 row updated. tkyte@TKYTE816> select ename, empno, sal 2 from emp, upper ename 3 where emp.rowid = upper ename.x$rid 4 and upper ename.x$ename = KING ENAME EMPNO King 7839 tkyte@TKYTE816> delete from 3 select ename, empno 4 from emp 5 where emp.rowid in (select uppex ename.x$rid 6 from upper ename 7 where x$ename = KINS} 1 row deleted. При выборе можно использовать подзапрос с IN либо соединение (JOIN). Из-за правил сохранения ключей при изменении или удалении строки надо использовать только подзапрос с IN. Примечание об этом методе, требующем сохранения идентификаторов строк: организованную по индексу таблицу, как и любой другой индекс, необходимо перестраивать, если в результате выполненных действий, таких как экспорт и импорт или применение оператора ALTER TABLE MOVE, изменились идентификаторы строк в таблице ЕМР. Наконец, если необходимо обеспечить совместное размещение данных или физически хранить данные в определенном порядке, индексная организация таблицы тоже подойдет. Пользователи СУБД Sybase и SQL Server в этом случае использовали бы кластерный индекс, но организация таблицы по индексу намного лучше. В случае кластерного индекса в этих СУБД может дополнительно расходоваться до 110 процентов пространства (аналогично моей таблице KEYWORDS в представленном ранее примере). Здесь же дополнительных расходов вообще нет, поскольку данные хранятся только в одном месте. Классический пример желательности совместного размещения взаимосвязанных данных представляет собой отношение главный/подчиненный. Пусть у таблицы ЕМР имеется подчиненная таблица: tkyte@TKYTE816> create table addresses 2 (empno number(4) references emp(empno) on delete cascade, 3 addr type varchar2(10) , 4 street varchar2(20) , 5 city varchar2(20) , 6 state varchar2(2), 7 zip number, 8 primary key (empno,addr type) 10 ORGANIZATION INDEX 11 / Table created. Физически близкое размещение всех адресов сотрудника (домашнего адреса, адреса места работы, адреса школы, прежнего адреса и т.д.) уменьшит объем ввода/вывода при соединении таблиц ЕМР и ADDRESSES. Объем логического ввода/вывода будет тем же, но физического ввода/вывода потребуется существенно меньше. В обычной таблице каждый адрес сотрудника может физически находиться в другом блоке по отношению к другим адресам того же сотрудника. Сортируя адреса по столбцам EMPNO и ADDRTYPE, мы гарантируем, что все адреса данного сотрудника хранятся рядом . Это применимо и в случае частого использования запросов с конструкцией BETWEEN по первичному или уникальному ключу. Хранение отсортированных данных повысит производительность и этих запросов. Например, в моей базе данных имеется таблица котировок акций. Каждый день в нее собирается информация о символах акций, дате, конечной цене, колебаниях курса в течение дня, количестве проданных акций и т.д. Это делается для акций сотен компаний. Соответствующая таблица имеет такой вид: tkyte@TKYTE816> create table stocks
Table created. Я часто просматриваю котировки акций одной компании, за некоторый период (вычисляя скользящее среднее, например). При использовании таблицы, организованной в виде кучи, вероятность того, что две строки для акций ORCL окажутся в одном блоке базы данных, практически равна нулю. Дело в том, что каждую ночь вставляются записи за день для всех акций. При этом заполняется как минимум один блок базы данных (обычно - много блоков). Поэтому каждый день мы добавляем новую запись для акций ORCL, но она попадает в блок, не совпадающий с другими, содержащими записи для ORCL, блоками таблицы. Если выполнить запрос: Select * from stocks where ticker = ORCL and day between sysdate and sysdate - 100; сервер Oracle прочитает индекс, а затем обратится к таблице за остальными данными строки по идентификатору строки. Каждая из 100 выбираемых строк окажется в другом блоке базы данных из-за принятого способа загрузки данных в таблицу, и каждая, вероятно, потребует выполнения операции физического ввода/вывода. Теперь предположим, что такая таблица организована по индексу. При выполнении этого же запроса придется прочитать только соответствующие блоки индекса, и все необходимые данные будут получены. Не только нет необходимости обращаться к таблице, но и все строки для акций ORCL в заданном диапазоне дат физически хранятся рядом друг с другом. Требуется меньше логического и физического ввода/вывода. Теперь понятно, когда следует использовать таблицы, организованные по индексу, и как это делать. Осталось разобраться, какие опции можно использовать при создании таких таблиц? Есть ли потенциальные проблемы при их использовании? Опции те же, что задаются для таблиц, организованных в виде кучи. Еще раз воспользуемся утилита-
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.002
При копировании материалов приветствуются ссылки. |