|
Программирование >> Oracle
Этот рисунок показывает, что отметка максимального уровня сначала указывает на первый блок только что созданной таблицы. По мере добавления данных в таблицу и использования новых блоков отметка максимального уровня повышается. Если удалить некоторые (или даже все) строки таблицы, может появиться много блоков, уже не содержащих данные, но они все равно находятся до отметки максимального уровня и останутся там, пока объект не будет пересоздан или усечен. Отметка максимального уровня важна, поскольку сервер Oracle при полном просмотре будет сканировать все блоки до этой отметки, даже если они не содержат данных. Это скажется на скорости выполнения полного просмотра, особенно если большая часть блоков до отметки максимального уровня - пустые. Чтобы убедиться в этом, просто создайте таблицу из 1000000 (или другого большого количества) строк. Выполните запрос SELECT COUNT(*) к этой таблице. Теперь удалите все строки таблицы и убедитесь, что запрос SELECT COUNT(*), не возвращающий строк, работает так же долго, как и в случае возвращения 1000000 строк. Так происходит потому, что сервер Oracle просматривает все блоки до отметки максимального уровня в поисках данных. Сравните это с результатом применения оператора TRUNCATE. При выполнении TRUNCATE отметка максимального уровня будет сброшена в ноль . Если предполагается удаление всех строк таблицы, именно по этой причине надо использовать оператор TRUNCATE. Списки свободных мест В списке свободных мест (FREELIST) сервер Oracle отслеживает блоки объекта до отметки максимального уровня, в которых есть свободное пространство. С каждым объектом будет связан хотя бы один список свободных мест, и по мере использования блоков они будут при необходимости добавляться или удаляться из этого списка. Важно отметить, что в списке свободных мест будут только блоки, находящиеся до отметки максимального уровня. Блоки за отметкой максимального уровня будут использоваться, только когда списки свободных мест пусты, - в этот момент сервер Oracle переносит отметку максимального уровня дальше и добавляет соответствующие блоки в список свободных мест. Таким образом, сервер Oracle откладывает увеличение отметки максимального уровня для объекта, пока это не станет действительно необходимым. У объекта может быть несколько списков свободных мест. Если предполагается выполнение значительного количества операций INSERT или UPDATE для объекта множеством одновременно работающих пользователей, создание нескольких списков свободных мест может существенно повысить производительность (за счет возможного использования дополнительной памяти). Как будет показано далее, наличие достаточного количества списков свободных мест принципиально важно. В среде с множеством одновременных вставок или изменений данных списки свободных мест могут как снижать так и повышать производительность. Предельно простой тест может показать преимущества установки подходящего количества списков свободных мест. Берем простейшую таблицу: tkyte@TKYTE816> create table t (x int) ; и с помощью двух сеансов начинаем интенсивно вставлять в нее данные. Если измерить общесистемное количество ожиданий событий, связанных с блоками, до и после этой операции, можно выявить продолжительные ожидания доступности блоков данных (при вставке данных). Это зачастую вызвано недостаточным количеством списков свободных мест в таблицах (и в индексах, но к индексам мы еще вернемся в главе 7). Итак, я создал временную таблицу: tkyte@TKYTE816> create global temporary table waitstat before 2 on commit preserve rows 3 as 4 select * from v$waitstat 5 where 1=0 Table created. для хранения исходного количества ожиданий блоков. Затем в двух сеансах я одновременно выполнил: tkyte@TKYTE816> truncate table waitstat before; Table truncated. tkyte@TKYTE816> insert into waitstat before 2 select * from v$waitstat 14 rows created. tkyte@TKYTE816> begin 2 for i in 1 . . 100000 3 loop 4 insert into t values (i) ; 5 commit; 6 end loop; 7 end; 8/ PL/SQL procedure successfully completed. Это - очень простой блок кода, и мы - единственные пользователи базы данных в этот момент. Производительность при этом должна быть максимальной. У меня создан большой буферный кэш, журналы повторного выполнения имеют нужный размер, индексы не замедляют работу; все должно работать быстро. В результате, однако, я получаю следующее: tkyte@TKYTE816> select a.class, b.count-a.count count, b.time-a.time time 2 from waitstat before a, v$waitstat b 3 where a.class = b.class CLASS COUNT TIME bitmap block 0 0
В ходе одновременной работы этих сеансов пришлось ждать более 32 секунд. Это целиком следствие недостаточного количества списков свободных мест для одновременного выполнения подобного рода действий. Можно легко вообще избавиться от этого ожидания, просто создав таблицу с несколькими списками свободных мест: tkyte@TKYTE816> create table t (x int) storage (FREETS 2); Table created, или изменив уже существующий объект: tkyte@TKYTE816> alter table t storage (FREELISTS 2) ; Table altered. Теперь можно убедиться, что оба показанных ранее времени ожидания свелись к нулю. Для таблицы необходимо попытаться определить максимальное количество одновременных вставок или изменений, для выполнения которых потребуется выделение дополнительного пространства. Под одновременностью я имею в виду ситуации, когда несколько сеансов в один и тот же момент будут запрашивать свободный блок для соответствующей таблицы. Речь не идет о количестве одновременно выполняющихся транзакций - нас интересует, сколько сеансов будет одновременно выполнять вставку, независимо от границ транзакций. Для достижения максимального параллелизма необходимо как минимум столько списков свободных мест, сколько вставок одновременно выполняется в таблицу. Значит, задав большое значение параметра FREELIST, можно забыть про все эти проблемы, верно? Нет, - это б1ло бы слишком просто. Каждый процесс будет использовать один список свободных мест. Он не будет при поиске свободного места переходить от одного списка к другому. Это означает, что если в списке, используемом процессом, свободного места не осталось, он не будет искать свободное место в другом списке. И хотя в таблице имеется десять списков свободных мест, будет передвинута отметка максимального уровня для таблицы. Если же передвигать отметку некуда (все пространство использовано), будет выделен новый экстент. Затем процесс продолжит использовать пространство только в своем списке свободных мест (который сейчас пуст). При использовании нескольких списков свободных мест приходится идти на компромисс. С
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |