|
Автор: Александр ДЕНИСЕНКО aden@online.ru, aledin@academy.ru Расслоение таблицы - это её представление в виде совокупности других таблиц и алгоритм её синтеза. В большинстве баз имеется механизм виртуальных таблиц или видов (view). Как правило, виртуальная таблица для наблюдателя вообще неотличима от реальной. Простейший пример такого рода - разбиение таблицы Т на две части и оператор UNION в качестве алгоритма синтеза. Как правило, разбиение производится на непересекающиеся части и таблица эквивалентна виду: Select * from T1 UNION Select * from T2 Это позволяет администратору базы переопределять источник данных в процессе эксплуатации, не затрагивая программного кода разработчика. Оператор синтеза является некоторым аналогом объединения множеств. К сожалению, в распространенных базах типа [1] нет явного оператора разности двух таблиц. Мы покажем некоторые дополнительные возможности подобных механизмов, которые могут оказаться полезными для администратора (постараемся показать на примерах). Рассмотрим в качестве примера таблицу T, имеющую одно ключевое поле К и несколько не ключевых полей - F1,…,FN. Разобьём нашу таблицу по горизонтали на три части, диапазоны ключей которых могут пересекаться (состав их полей идентичен). Назовем эти части T0, T+ и T- и в качестве алгоритма синтеза примем такой оператор: SELECT * FROM T0 Where K not in (select K from T-) Union Select * from T+ Назовем часть (слой) T1 статической, а части (слои) T+ и T- назовём динамическими (положительной и отрицательной поправкой соответственно). Теперь подменим операции изменения таблицы следующим образом: - добавление новой строки - это её добавление в T+ Напомним, что в [1]
для этого служит развитой механизм триггеров. 1. Раздельная оптимизация Предположим, что темп обновления исходной таблицы невелик по сравнению с её размером. Например, в справочник из миллиона строк в течение некоторого цикла (сутки или неделя) вносится (удаляется, изменяется) несколько тысяч строк. Оптимизация хранения такой таблицы, как правило, является компромиссом между тремя параметрами: - размер занимаемой физической памяти; Любая пара этих параметров допускает оптимизацию лишь ценой третьего. Для иллюстрации вспомним оптимизацию индексов в [1]. Например, если процент заполнения индексных страниц сделать небольшим, то можно достичь высокой скорости поиска и сравнительно неплохой производительности при изменении; однако это приведёт к большому расходу памяти, занимаемой таблицей. Воспользуемся приведенным выше представлением и алгоритмом синтеза. Все поправки к таблице перенаправим в корректирующие слои (которые необходимо периодически подливать к статической части по окончании цикла - например, в конце смены или в выходные - как правило, массовая корректировка значительно эффективнее построчной). Теперь выберем высокий процент (fillfactor) заполнения для T0 (100 процентов) и низкий для динамических частей (например, десять процентов). Если наша таблица имеет порядка миллиона строк, то мы увеличиваем расход памяти в десять раз только для динамических слоёв. На практике замедление поиска в расслоённой таблице не сильно заметно при сравнительно небольших объёмах части T- (до нескольких сотен или тысяч строк - желательно, чтобы отрицательный слой оставался резидентным в быстрой памяти). Это связано с особенностями реализации физического хранения строк в [1]. Принципиально сложность операции вычитания не должна отличаться от суммы (как с числами в процессоре), но это требует специальных приёмов хранения. 2. Восстановление первоначального состояния. При необходимости вернуть таблицу в состояние на момент начала цикла (на утро, например) достаточно изменить описание вида (alter view в [1] - операция мгновенная, в отличие от восстановления баз). Если создать более чем по одной динамической части для добавления и удаления, то можно выполнять моментальный откат таблицы на соответствующий моменту набор слоёв. 3. Индивидуальность и защита Мы получили любопытный эффект - физическая защита исходного состояния таблицы при допущении логического внесения поправок. Динамические слои можно сделать вообще индивидуальными для наблюдателя и отпадает необходимость запрета модификации исходной таблицы. В самом деле, получая доступ к общему справочнику, наблюдатель волен логически вносить любые правки, не задевая физически ресурс (пользование правами не должно наносить ущерб правам другого человека). Более того, каждый может получить индивидуальное
представление общего ресурса. Это из Стругацких ('каждый
слышит свою трубку' - Улитка на склоне). 4. Снижение конфликтов Индивидуальность динамических слоёв для наблюдателя позволяет уменьшить накладные расходы при разрешении конфликтов - ряд блокировок становятся излишними. Каждый волен вносить изменения одновременно с другими наблюдателями, но в свои собственные слои. Видимость или невидимость слоя для того или иного наблюдателя реализуется сравнительно быстрой операцией изменения вида (опять alter view). Помните старика Хоттабыча на стадионе (дайте им каждому по мячу). 5. Перестроение на марше: 365*24 Так условно называют систему, которая должна обслуживать наблюдателя круглогодично и круглосуточно (даже если дней в году 366!). Администраторы многих систем сталкиваются со следующей проблемой: необходимо периодически реорганизовывать базу, сохраняя её доступность. Например, перестроение индексов приводит к потере доступности базы из-за блокировок; иногда необходимо отформатировать диск, на котором размещена база и т.д. Опишем кратко динамический процесс периодического изъятия копии базы с целью её модификации с последующим плавным переключением наблюдателей на обработанную копию. В этом случае без двух копий не обойтись. Для переключения наблюдателей между копиями воспользуемся динамическим формированием имени базы (переменная). Если в какой-то момент N наблюдателей работают с базой, то мы не можем их отключить ни на секунду, но можно вновь подключающихся наблюдателей перенаправлять ко второй копии. Разумеется, для этого потребуются и два экземпляра динамических слоёв - чтобы базы были клонами - то есть их состояния совпадали в любой момент (это достигается либо дублированием операций изменения базы, либо встречными триггерами на двух экземплярах динамических слоёв). Так со временем все соединения окажутся установленными со вторым экземпляром базы. Это означает, что первый экземпляр можно отсоединить (detach) или перевести в автономный режим, затем перенести его на другую машину и 'причесать' - например, перестроить индексы, убрать разрывы и физическую фрагментацию. В это время динамические слои второго экземпляра также должны быть задублированы. Теперь физически возвращаем первый экземпляр (причёсанный) и переключаем наблюдателей на него по мере возникновения новых соединений. Мы исходим из того, что все наблюдатели рано или поздно отсоединятся от второго экземпляра. Совокупность первого причёсанного экземпляра и второй копии динамических слоёв (собранных за время причёсывания) и даёт нужный результат. |
Автор: Александр Денисенко 2003г. |