Разбиваем БД на области

Готовим статьи для FAQ
Аватара пользователя
Arelav
Администратор
Сообщения: 1881
Зарегистрирован: 25 мар 2005, 17:05
Откуда: Progress Technologies
Контактная информация:

Сообщение Arelav » 20 авг 2006, 17:58

George писал(а):Мы с dmitri, похоже, тебя не убедили, что лучше разделить сам скрипт (логику выполнения команд) и входные данные (список таблиц).

Нет, не то чтобы не убедили, даже наоборот, просто как всегда,
в памяти нечто вертится, а вот что - ни как вспомнить не мог, вот и пропустил, оставив без изменения эту часть :D Бывает...
George писал(а):Для дампирования список таблиц можно "выковырять" из dbanalys'а

имеется ввиду скриптом парсить dbanalys, и брать для дампа только те таблицы, у которых колонка с количеством записей не равна нулю, нулевые игнорировать?
Только вот зачем? Обработка таких таблиц времени при дампе и не увеличивает.
George писал(а):Кстати в скрипт стоит добавил проверку сообщений бинарного дампа, отфильтровав все "обычные" сообщения, а все "необычные" сообщения сбрасывать в специальный лог

А как отличить "обычные" от "необычных"?

George писал(а):Таблицы _seqvals не существует да и значения сиквенций не хранятся ни в какой таблице.

Хорошо, но ведь текущие значения счетчиков нужны все равно, как правильно дать формулировку, точнее немного ввести в курс читатель - откуда берутся эти значения?

George писал(а):Утилиту prostrct create стоит забыть за ненадобностью.

Согласен, procopy сам создаст структуру по st-файлу. Но и забывать о prostrct create тоже не стоит.

George писал(а):Такое редактирование df-файла реального приложения было бы героическим подвигом.

Это уж точно :D , а статью я кажется, пропустил, или забыл про неё, ща будут искать. :wink:

А вообще, у меня база сейчас в 40 Gb, пока есть возможность, наверное попробую еще раз тестовый забег на D&L 8)

Аватара пользователя
Arelav
Администратор
Сообщения: 1881
Зарегистрирован: 25 мар 2005, 17:05
Откуда: Progress Technologies
Контактная информация:

Сообщение Arelav » 20 авг 2006, 19:02

Здесь на форуме обсуждался скрипт, который работает на основе списка для переноса таблиц:

Это не этот ли? ".df converter"
http://forum.infobit.ru/viewtopic.php?p ... +area#3762

Аватара пользователя
George
Старожил
Сообщения: 2871
Зарегистрирован: 12 май 2004, 17:03
Откуда: Питер

Сообщение George » 20 авг 2006, 21:55

Валерий писал(а):имеется ввиду скриптом парсить dbanalys, и брать для дампа только те таблицы, у которых колонка с количеством записей не равна нулю, нулевые игнорировать?
Только вот зачем? Обработка таких таблиц времени при дампе и не увеличивает.

Я сразу и ответил - так будет глазу приятней. :wink: На диске будет лежать только то, что надо грузить.

Это было не предложение, а публичное размышление. Вполне возможно, что риск нарваться на ошибку скрипта при разборе результатов dbanalys'а не стоит призрачной выгоды от минимизации числа дамп-файлов.

А как отличить "обычные" от "необычных"?

Все сообщения, что пишутся при дампе любой таблицы - "обычные". Все, что может возникнуть сверх того - "необычные". Т.е. предлагается использовать grep -v по небольшому списку "обычных" сообщений.

Хорошо, но ведь текущие значения счетчиков нужны все равно, как правильно дать формулировку, точнее немного ввести в курс читатель - откуда берутся эти значения?

Есть пункт меню в Data Dictionary - дампирование текущих значений секвенций.
Согласен, procopy сам создаст структуру по st-файлу. Но и забывать о prostrct create тоже не стоит.

Зачем может понадобиться эта утилита?

Это не этот ли? ".df converter"

Да, я имел ввиду этот скрипт.

Аватара пользователя
Arelav
Администратор
Сообщения: 1881
Зарегистрирован: 25 мар 2005, 17:05
Откуда: Progress Technologies
Контактная информация:

Сообщение Arelav » 28 авг 2006, 05:26

Есть пункт меню в Data Dictionary - дампирование текущих значений секвенций.

В принципе, я это и имел ввиду. Просто, как всегда у меня бывает, это было "между строк" :lol:
Получается, значения секвенций прошиты где-то внутри базы, и это не таблица, хотя при выгрузке из Data Dictionary, формируется файл _seqdefs.df, что и ввело меня в заблуждение, на счет наличия такой таблицы. :-?
И все таки, игде конкретно (физически) хранятся эти данные? :-?
Зачем может понадобиться эта утилита?

Хотя бы для того, чтобы человечек читающий мануал знал о существовании такой команды :)

Аватара пользователя
George
Старожил
Сообщения: 2871
Зарегистрирован: 12 май 2004, 17:03
Откуда: Питер

Сообщение George » 28 авг 2006, 11:20

Валерий писал(а):И все таки, игде конкретно (физически) хранятся эти данные? :-?

В специальном блоке для значений секвенций. На каждую секвенцию в нем выделено 4-ре байта. Номер секвенции связан с местоположением значения данной секвенции внутри блока. Блок один на базу. Практически всегда он является третим блоком в Schema Area. Исключение - если база конвертировалась из древней версии Progress'а через conv* утилиты.

Возвращаясь к дампированию значений секвенций... Есть системная таблица _Sequence, но она содержит только описания секвенций. Для дампа значений в Progress V10 можно использовать динамический доступ к секвенциям:

Код: Выделить всё

DYNAMIC-CURRENT-VALUE(sequence-expression, logical-dbname)


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

Код: Выделить всё

PUT "CURRENT-VALUE(" + _Sequence._Seq-Name + ")" SKIP

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

Хотя бы для того, чтобы человечек читающий мануал знал о существовании такой команды :)

Если он забудет о существовании prostrct create, то в будущем у него будет меньше проблем.

Аватара пользователя
dmi
Старожил
Сообщения: 1523
Зарегистрирован: 27 сен 2001, 03:00
Откуда: Москва
Контактная информация:

Сообщение dmi » 24 янв 2007, 14:10

Валерий писал(а):
К процедуре дампирования я бы добавил запуск dbanаlys'а непосредствено пред дампом. Во-первых, будет возможность проверить, что во время "переправы" ни одна запись не утонула.


А у всех свои волшебные утилиты сравнения dbanalys? Тут не писал их никто.
Могу свою программу предложить на публичное растерзание, если надо.
Она читает dbanalys (что касается таблиц) и во временную таблицу кладет.

Вернее - это не программа, а конструктор :) - просто основываясь на данных dbanalys можно написать,например, параллельный запуск дампов мелких таблиц,
если экстенты на разных физустройствах - параллельно поэкстентно.
Реально время сокращает.


После формирования скриптов выгрузки и загрузки, необходимо сформировать df-файл всех таблиц БД, через Dump Data and Definitions редактора Progress. А также выгрузить данные по пользователям – таблица _user и значения сиквенсов – таблица _seqvals.


В некоторых софтах есть hidden-таблицы (не схема). (это если документация универсальная пишется). Надо и на это внимание обратить.

Копирование БД с эталона, происходит следующей командой:
Procopy /usr/dlc/empty <newdbname>


А если сразу procopy $DLC/empty<block> <newdbname> - и если есть
st то все то же самое.

А вот объясните:

Примечание: загрузка данных будет происходить быстрее, если база данных будет запущена в многопользовательском режиме в режиме no-integrity (-i).


и

Согласен с важности no-integrity моды. Но при этом базу все равно стоит запускать в многопользовательском режиме (и еще при этом запустить фоновые процессы - APW - несколько - и BIW). Тогда параметр -i (и -G 0) при запуске proutil -C load будут проигнорированы.


Непонятно (по крайней мере мне :)

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


Далее - какие таблицы грузить первыми? По каким критериям? Большие таблицы? Маленькие? Сортировать по размеру записи?

(ProKB читал, peg тоже) - просто интересно, кто как делает.

/dmi

Аватара пользователя
George
Старожил
Сообщения: 2871
Зарегистрирован: 12 май 2004, 17:03
Откуда: Питер

Сообщение George » 24 янв 2007, 17:01

dmi писал(а):А у всех свои волшебные утилиты сравнения dbanalys?

У меня тоже написана такая програмка. Крен был сделан в универсальность по версиям Progress'а (правила вывода информации слегка вариировались от версии к версии).

Есть Tom Bascom's tba.p (reads tabanalys output):
http://www.greenfieldtech.com/downloads/files/tba.p

Что-то есть в Progress Knowledgebase:

KB-20491: Perl Program to Extract Table and Index Information
http://progress.atgnow.com/esprogress/G ... s&id=20491

KB-20490: Perl Program to Compare Two DBANALYS Files
http://progress.atgnow.com/esprogress/G ... s&id=20490

Но лично я чаще преобразую файл с tabanalys'ом с помощью замен в Word'е.
В некоторых софтах есть hidden-таблицы (не схема). (это если документация универсальная пишется). Надо и на это внимание обратить.

А от кого эти таблицы прячутся и зачем?
Конечные пользователь и так доступа к схеме не имеет.
Админ базы знает где включить Show Hidden Tables.

О важности no-integrity моды...
Непонятно (по крайней мере мне :)

А что непонятно? То, что вторая цитата как бы спорит с первой, хотя обе говорят по-сути об одном и том же? Так документ редактировался.
Далее - какие таблицы грузить первыми? По каким критериям? Большие таблицы? Маленькие? Сортировать по размеру записи?

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

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

Аватара пользователя
dmi
Старожил
Сообщения: 1523
Зарегистрирован: 27 сен 2001, 03:00
Откуда: Москва
Контактная информация:

Сообщение dmi » 24 янв 2007, 18:04

George писал(а):У меня тоже написана такая програмка. Крен был сделан в универсальность по версиям Progress'а (правила вывода информации слегка вариировались от версии к версии).
Есть Tom Bascom's tba.p (reads tabanalys output):
http://www.greenfieldtech.com/downloads/files/tba.p


Видел.
Для 9.1D следующиее придумал на основе вышеупомянутой программы:

Код: Выделить всё

&IF FALSE &THEN
/*
 * $Log: $
 *
 * parse dbanalys log for record block data
 * /dmi
 *
 */
&ENDIF


DEF STREAM dbanalys.

DEF VAR std-ch           AS CHARACTER NO-UNDO.
DEF VAR p-dbanalys-name  AS CHARACTER NO-UNDO INIT "c:\test\dbanalys".
DEF VAR p-dbanalys-after AS CHARACTER NO-UNDO INIT "c:\test\dbanalys-after".
DEF VAR p-result-file    AS CHARACTER NO-UNDO INIT "c:\test\compare".
DEF VAR p-delta          AS INTEGER   NO-UNDO.
DEF VAR p-stat           AS CHARACTER EXTENT 10.
DEF VAR p-idx            AS INTEGER   NO-UNDO.

DEF TEMP-TABLE tt-area NO-UNDO
    FIELD p-area-num AS INTEGER
    FIELD p-seq      AS INTEGER
    FIELD p-area     AS CHARACTER
INDEX pi-tt-area IS UNIQUE PRIMARY p-area-num p-seq.

DEF TEMP-TABLE tt-dbanalys NO-UNDO
    FIELD p-area-num   AS INTEGER
    FIELD p-table      AS CHARACTER
    FIELD p-seq        AS INTEGER
    FIELD p-records    AS INTEGER
    FIELD p-dec-size   AS DECIMAL
    FIELD p-size       AS CHARACTER
    FIELD p-recmin     AS INTEGER
    FIELD p-recmax     AS INTEGER
    FIELD p-recmean    AS INTEGER
    FIELD p-fragcnt    AS INTEGER
    FIELD p-fragfactor AS DECIMAL
    FIELD p-scatter    AS DECIMAL
    FIELD p-marked     AS LOGICAL INIT NO
INDEX pi-tt-dbanalys IS UNIQUE PRIMARY p-area-num p-table p-seq.

/*******************************************************************/
/******** M A I N **************************************************/
/*******************************************************************/

/* before */
RUN load-dbanalys(0).

/* after */
RUN load-dbanalys(1).

/*RUN generate-d-script.p*/
/*RUN generate-l-script.p*/

RUN compare-records.

/********************************************************************/
/******** Load dbanalys *********************************************/
/********************************************************************/
PROCEDURE load-dbanalys:
    DEF INPUT PARAMETER p-mode AS INTEGER NO-UNDO.

    IF p-mode = 0 THEN
       INPUT STREAM dbanalys FROM VALUE(p-dbanalys-name).
    ELSE
       INPUT STREAM dbanalys FROM VALUE(p-dbanalys-after).

  main:
  REPEAT:
      IMPORT STREAM dbanalys UNFORMATTED std-ch.
      /* parse db table statistics */
      IF std-ch BEGINS "RECORD BLOCK SUMMARY FOR AREA" THEN DO:
          /* get area name and number */
          CREATE tt-area.
          ASSIGN
            tt-area.p-area     = ENTRY(1,SUBSTRING(std-ch,32),"""")
            tt-area.p-area-num = INTEGER(TRIM(ENTRY(2,std-ch,":")))
            tt-area.p-seq      = p-mode
          .

          /*{str-skip.i &expect="Table" &loop-label=ttable &addl-action='IF TRIM(std-ch) BEGINS "INDEX BLOCK SUMMARY" THEN LEAVE main.'}*/
          /* get table name and information */
          ttable:
           REPEAT:
             IMPORT STREAM dbanalys UNFORMATTED std-ch.
              IF TRIM(std-ch) BEGINS "INDEX BLOCK SUMMARY" THEN LEAVE main.
              IF TRIM(std-ch) BEGINS "Table" THEN LEAVE ttable.
           END.

         get-table:
         REPEAT:
          IMPORT STREAM dbanalys p-stat.
          IF p-stat[1] = "" THEN LEAVE get-table.
          CREATE tt-dbanalys.
          ASSIGN
            tt-dbanalys.p-area-num  = tt-area.p-area-num
            tt-dbanalys.p-table     = IF NOT p-stat[1] BEGINS "_" THEN SUBSTRING(p-stat[1],5) ELSE p-stat[1]
            tt-dbanalys.p-seq       = p-mode
            p-delta = 0
          .

          /* process long table name */
          IF p-stat[2] = "" THEN DO:
              IMPORT STREAM dbanalys p-stat.
              p-delta = -1.
          END.

          ASSIGN
           tt-dbanalys.p-records    = INTEGER(p-stat[2 + p-delta])
           tt-dbanalys.p-size       = p-stat[3 + p-delta]
           tt-dbanalys.p-recmin     = INTEGER(p-stat[4 + p-delta])
           tt-dbanalys.p-recmax     = INTEGER(p-stat[5 + p-delta])
           tt-dbanalys.p-recmean    = INTEGER(p-stat[6 + p-delta])
           tt-dbanalys.p-fragcnt    = INTEGER(p-stat[7 + p-delta])
           tt-dbanalys.p-fragfactor = DECIMAL(p-stat[8 + p-delta])
           tt-dbanalys.p-scatter    = DECIMAL(p-stat[9 + p-delta])
          .

          CASE SUBSTRING(tt-dbanalys.p-size, LENGTH( tt-dbanalys.p-size ), 1 ):
              WHEN "G" THEN DO:
                  tt-dbanalys.p-dec-size = DECIMAL(SUBSTRING(tt-dbanalys.p-size,1,LENGTH(tt-dbanalys.p-size) - 1)) * 1073741824.
              END.
              WHEN "M" THEN DO:
                  tt-dbanalys.p-dec-size = DECIMAL(SUBSTRING(tt-dbanalys.p-size,1,LENGTH(tt-dbanalys.p-size) - 1)) * 1048576.
              END.
              WHEN "K" THEN DO:
                  tt-dbanalys.p-dec-size = DECIMAL(SUBSTRING(tt-dbanalys.p-size,1,LENGTH(tt-dbanalys.p-size) - 1)) * 1024.
              END.
              WHEN "B" THEN DO:
                   tt-dbanalys.p-dec-size = DECIMAL(SUBSTRING(tt-dbanalys.p-size,1,LENGTH(tt-dbanalys.p-size) - 1)).
              END.
              OTHERWISE  tt-dbanalys.p-dec-size = ?.
          END CASE.

          tt-dbanalys.p-dec-size = tt-dbanalys.p-dec-size / 1048576. /* Size in Mb */

          DO p-idx = 1 TO 10:
              p-stat[p-idx] = "".
          END.

         END. /* get table info */
      END. /* Records block summary */
  END.
  INPUT STREAM dbanalys CLOSE.
END PROCEDURE.

/************************************************************************************/
/******** Compare records ***********************************************************/
/************************************************************************************/
PROCEDURE compare-records:

    DEF VAR p-error AS LOGICAL INIT FALSE.
    DEF BUFFER x-tt-dbanalys FOR tt-dbanalys.
    OUTPUT TO VALUE(p-result-file).

    FOR EACH tt-dbanalys WHERE NOT p-table BEGINS "_" AND p-seq = 0:
        PUT UNFORMATTED "Check : " p-table " ".
        FIND FIRST x-tt-dbanalys WHERE x-tt-dbanalys.p-table = tt-dbanalys.p-table AND
                                       x-tt-dbanalys.p-seq   = 1 NO-LOCK NO-ERROR.

        IF NOT AVAIL x-tt-dbanalys THEN DO:
            PUT UNFORMATTED SKIP "*** ERROR1: " tt-dbanalys.p-table " not found" SKIP.
            p-error = YES.
        END.
        ELSE DO:
            IF tt-dbanalys.p-records <> x-tt-dbanalys.p-records THEN DO:
                PUT UNFORMATTED SKIP "*** ERROR2: " tt-dbanalys.p-table " has " x-tt-dbanalys.p-records " instead " tt-dbanalys.p-records SKIP.
                p-error = YES.
            END.
            ELSE PUT UNFORMATTED " OK!" SKIP.
        END.

    END.
    PUT UNFORMATTED SKIP(5).
    IF p-error THEN PUT UNFORMATTED "**** ERROR".
    OUTPUT CLOSE.

END PROCEDURE.


Вроде работает :) Я на тесте проверял, расхождение в количестве записей ловит.

В некоторых софтах есть hidden-таблицы (не схема). (это если документация универсальная пишется). Надо и на это внимание обратить.

А от кого эти таблицы прячутся и зачем?
Конечные пользователь и так доступа к схеме не имеет.
Админ базы знает где включить Show Hidden Tables.


Ну из-за архитектуры софта - возможность расширения таблиц своими полями. В моем прошлом софте было. Про то, что админы знают :) - я бы не закладывался. По опыту.

О важности no-integrity моды...
Непонятно (по крайней мере мне :)

А что непонятно? То, что вторая цитата как бы спорит с первой, хотя обе говорят по-сути об одном и том же? Так документ редактировался.


Я прочел, что запуск multi-user с proapw/probiw/итд отменяет -i режим.
Это же не так?
Надо сервер с -i запускать? Я здесь запутался.

Далее - какие таблицы грузить первыми? По каким критериям? Большие таблицы? Маленькие? Сортировать по размеру записи?

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


Спасибо, то есть информации dbanalys достаточно для такой загрузки.

/dmi

Аватара пользователя
George
Старожил
Сообщения: 2871
Зарегистрирован: 12 май 2004, 17:03
Откуда: Питер

Сообщение George » 24 янв 2007, 18:44

dmi писал(а):Я прочел, что запуск multi-user с proapw/probiw/итд отменяет -i режим.
Это же не так?
Надо сервер с -i запускать? Я здесь запутался.

Сервер имеет смысл запускать с ключем -i.

Ключ игнорируется для клиентских сессий (например, для proutil -C load), которые подключаются к уже запущенной базе. Т.е. по какому правилу будет проходить работа с bi файлом (с поддержкой целостности или без нее) определяется только процессом, открышив базу.

xGoodWin
Старожил
Сообщения: 16
Зарегистрирован: 16 ноя 2007, 16:48
Контактная информация:

Сообщение xGoodWin » 05 апр 2008, 19:36

George писал(а):Есть пункт меню в Data Dictionary - дампирование текущих значений секвенций.


Коллеги, помогите разобраться с этими сиквенсами.
Сделал дамп сиквенсов:
Data Dictionary -> Admin -> Dump Data and Definitions -> Sequences Definitions...
(Здесь я так понимаю можно сдампировать только структуру сиквенсов)
Есть строчка ниже:
Data Dictionary -> Admin -> Dump Data and Definitions -> Sequences Current Values...
Но она мне недоступна! Курсор просто перескакивает ее.

Как загрузить текущие значения счетчиков?

Аватара пользователя
George
Старожил
Сообщения: 2871
Зарегистрирован: 12 май 2004, 17:03
Откуда: Питер

Сообщение George » 06 апр 2008, 23:03

xGoodWin писал(а):Data Dictionary -> Admin -> Dump Data and Definitions -> Sequences Current Values...
Но она мне недоступна! Курсор просто перескакивает ее.

Нужна 4GL лицензия

Аватара пользователя
dmi
Старожил
Сообщения: 1523
Зарегистрирован: 27 сен 2001, 03:00
Откуда: Москва
Контактная информация:

Сообщение dmi » 06 апр 2008, 23:05

George писал(а):
xGoodWin писал(а):Data Dictionary -> Admin -> Dump Data and Definitions -> Sequences Current Values...
Но она мне недоступна! Курсор просто перескакивает ее.

Нужна 4GL лицензия


-rx или как его там - не покатит?

upd: проверил - не прокатит :)
да, действительно:
----------------------------------------------------------------------
KB-P115824: Is it possible to dump and load SEQUENCES using the Data Administration tool with a Runtime license?
----------------------------------------------------------------------

Status: Unverified

GOAL:

Is it possible to dump and load SEQUENCES using the Data
Administration tool with a Runtime license?

FACT(s) (Environment):

Progress 8.x
Progress 9.x
OpenEdge 10.x

FIX:

It is not possible to dump and load SEQUENCES using the Progress Data
Administration tool with a Runtime license. Even adding the -rx
parameter will still not enable the "Sequence Current Values..." menu
option under the Admin | Dump/Load Data and Definitions section. A
development license is required to achieve this.

xGoodWin
Старожил
Сообщения: 16
Зарегистрирован: 16 ноя 2007, 16:48
Контактная информация:

Сообщение xGoodWin » 07 апр 2008, 00:38

Вы правы... Даже с -rx не получается.
Подозревал, что дело именно в отсутствии необходимой лицензии :(

Есть еще варианты дампа без лицензии 4GL?

Аватара пользователя
dmitri
Старожил
Сообщения: 1016
Зарегистрирован: 04 авг 2005, 16:19
Откуда: Pennsylvania, USA
Контактная информация:

Сообщение dmitri » 07 апр 2008, 00:38

Хотя бы одна 4GL лицензия нужна практически всем, кто работает с Progress. Если например 100 маленьких магазинчиков, то достаточно одну 4GL на все 100. У нас например 17 складов гоняют один и тот же код и 4GL лицензия не установлена ни на одном, а установлена в оффисе на Development.
Если приобрести 4GL лицензию не возможно по финансовым причинам, то надо рассмотреть возможность работы с MySQL или Postgress.
Последний раз редактировалось dmitri 07 апр 2008, 00:45, всего редактировалось 3 раза.

xGoodWin
Старожил
Сообщения: 16
Зарегистрирован: 16 ноя 2007, 16:48
Контактная информация:

Сообщение xGoodWin » 07 апр 2008, 00:41

dmitri писал(а):Хотя бы одна 4GL лицензия нужна практически всем, кто работает с Progress. Если приобрести её не возможно по финансовым причинам, то надо рассмотреть возможность работы с MySQL или Postgress.


ясно :-?