16 июн. 2010 г.

Неявные JOIN-ы

Такие вот запросы практиковались в раннем Гедымине:
SELECT
   isg2.RDB$FIELD_NAME       FirstField
   , rc2.RDB$RELATION_NAME   NetTable
   , isg4.RDB$FIELD_NAME     SecondField
   , rc5.RDB$RELATION_NAME   TargetTable
   , isg6.RDB$FIELD_NAME     TargetField 
   , (SELECT 1
     FROM RDB$DATABASE
     WHERE
       EXISTS(SELECT *
              FROM RDB$RELATION_FIELDS rf
              WHERE rc5.RDB$RELATION_NAME = rf.RDB$RELATION_NAME
               AND rf.RDB$FIELD_NAME = 'LB')
       AND EXISTS(SELECT *
              FROM RDB$RELATION_FIELDS rf
              WHERE rc5.RDB$RELATION_NAME = rf.RDB$RELATION_NAME
               AND rf.RDB$FIELD_NAME = 'RB')) IsTree
 FROM
   RDB$INDEX_SEGMENTS isg1
   , RDB$RELATION_CONSTRAINTS rc1
   , RDB$REF_CONSTRAINTS rfc1
   , RDB$RELATION_CONSTRAINTS rc2
   , RDB$INDEX_SEGMENTS isg2
   , RDB$INDEX_SEGMENTS isg3
   , RDB$RELATION_CONSTRAINTS rc3
   , RDB$INDEX_SEGMENTS isg4
   , RDB$INDEX_SEGMENTS isg5
   , RDB$RELATION_CONSTRAINTS rc4
   , RDB$REF_CONSTRAINTS rfc2
   , RDB$RELATION_CONSTRAINTS rc5
   , RDB$INDEX_SEGMENTS isg6 
 WHERE
   rc1.RDB$RELATION_NAME = :tablename
   AND rc1.RDB$INDEX_NAME = isg1.RDB$INDEX_NAME
   AND rc1.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'
   AND rfc1.RDB$CONSTRAINT_NAME = rc2.RDB$CONSTRAINT_NAME
   AND rfc1.RDB$CONST_NAME_UQ = rc1.RDB$CONSTRAINT_NAME
   AND rc2.RDB$INDEX_NAME = isg2.RDB$INDEX_NAME
   AND rc1.RDB$RELATION_NAME <> rc2.RDB$RELATION_NAME
   AND isg3.RDB$FIELD_NAME = isg2.RDB$FIELD_NAME
   AND rc3.RDB$RELATION_NAME = rc2.RDB$RELATION_NAME
   AND rc3.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'
   AND rc3.RDB$INDEX_NAME = isg3.RDB$INDEX_NAME
   AND isg4.RDB$INDEX_NAME = isg3.RDB$INDEX_NAME
   AND isg2.RDB$FIELD_NAME <> isg4.RDB$FIELD_NAME
   AND isg5.RDB$FIELD_NAME = isg4.RDB$FIELD_NAME
   AND rc4.RDB$INDEX_NAME = isg5.RDB$INDEX_NAME
   AND rc4.RDB$CONSTRAINT_TYPE = 'FOREIGN KEY'
   AND rc4.RDB$RELATION_NAME = rc2.RDB$RELATION_NAME
   AND rfc2.RDB$CONSTRAINT_NAME = rc4.RDB$CONSTRAINT_NAME
   AND rfc2.RDB$CONST_NAME_UQ = rc5.RDB$CONSTRAINT_NAME
   AND rc5.RDB$INDEX_NAME = isg6.RDB$INDEX_NAME 
Возвращает список атрибутов типа множество для заданной таблицы.

8 июн. 2010 г.

Предварительные результаты по внешним ключам

Для тестирования была использована действующая база ВМК размером 29,912,520 Кб. Были конвертированы все внешние целочисленные ключи, удовлетворяющие следующим условиям:
  • В таблице более 10 000 записей.
  • Уникальных значений в ключе не более 200.
  • Ключ не ссылается на эту же таблицу.
Всего ключей, удовлетворяющих условиям, набралось 266. После их удаления и процедуры бэкапа-разбэкапа базы ее размер уменьшился до 23,752,136 Кб или на 21%.

После этого мы проверили скорость выполнения запроса на изменение данных на таблице AC_ENTRY, которая содержит более 9 млн. записей. Текст команды приводится ниже:
update ac_entry set
  companykey = 147048034,
  usr$gs_department = 147048036,
  currkey = 147021255,
  usr$gs_service = 147089059
Четыре изменяемых поля — это сконвертированные ссылки. Проверка целостности осуществляется с помощью триггера следующего вида:
CREATE TRIGGER xxx ON AC_ENTRY
  AFTER UPDATE
  POSITION 32000
BEGIN 
  IF (NEW.USR$GS_SERVICE IS NOT DISTINCT FROM 
    OLD.USR$GS_SERVICE) THEN EXIT;

  IF (NEW.USR$GS_SERVICE IS NOT NULL) THEN 
  BEGIN 
    IF (NOT EXISTS (SELECT id FROM gd_ref_constraint_data 
      WHERE value_data = NEW.USR$GS_SERVICE 
        AND constraintkey = 388626603)) THEN 
    BEGIN
      IF (NOT EXISTS (SELECT ID FROM GD_GOOD 
          WHERE ID = NEW.USR$GS_SERVICE)) THEN
        EXCEPTION gd_e_fkmanager 'message';

      RDB$SET_CONTEXT('USER_TRANSACTION', 
        'REF_CONSTRAINT_UNLOCK', '1');
      INSERT INTO gd_ref_constraint_data 
        (constraintkey, value_data, value_count)
        VALUES 
        (388626603, NEW.USR$GS_SERVICE, 1);
      RDB$SET_CONTEXT('USER_TRANSACTION', 
        'REF_CONSTRAINT_UNLOCK', '0');
    END
  END
END
Время выполнения запроса:
  • На новой базе — 1945 сек.
  • На старой базе — 2642 сек.
Получаем ускорение на 26%. Окончательные выводы можно будет сделать после тестирования на 2-3-х других базах.

7 июн. 2010 г.

Тестирование подсистемы отчетов

При тестировании изменений в подсистеме отчетов мы постарались исключить фактор пропускной способности сети и производительности дисковой подсистемы. Использовался встроенный сервер Firebird 2.5. Данные генерировались с помощью хранимых процедур. Пример такой процедуры можно видеть ниже:
CREATE PROCEDURE tst_p_gen_str_data (i INTEGER)
  RETURNS (id INTEGER,
    s1 VARCHAR(60),
    s2 VARCHAR(60),
    s3 VARCHAR(60),
    s4 VARCHAR(60))
AS
BEGIN
  s1 = 'ABC dfg';
  s2 = '123 567 9874 10';
  s3 = 'qwertyuiop asdfghjl; xzcvnbvmn,m.';
  s4 = '';
  WHILE (i > 0) DO
  BEGIN
    id = :i;
    i = :i - 1;
  END
END
Тестировались следующие отчеты:
  1. Отчет по одному набору данных со строковыми полями.
  2. Отчет по одному набору данных с целочисленными полями.
  3. Отчет по двум наборам данных, связанных связью мастер-дитэйл. Наборы данных со строковыми полями.
Замеры выполнялись на втором построении отчета. Учитывалось время построения отчета и информация об использовании оперативной памяти, полученная с помощью программы Process Explorer.

Таблица с результатами находится здесь.

Вывод:
  • для отчетов мастер-дитэйл на двух датасетах разница незначительна — увеличение потребления памяти на 2% и ускорение на 6%.
  • для отчетов, основанных на одном наборе данных, достигается существенное ускорение в 35% при умеренном росте потребления памяти — от 9 до 16%.
Стоит заметить, что Fast Report 4 позволяет строить отчеты с группировкой (фактически, мастер-дитэйл)  с использованием одного набора данных.

1 июн. 2010 г.

Проблема 1 июня 2010 года

В нашей истории случались забавные и не очень случаи, когда программа начинала работать неверно с определенной даты. Как выяснилось, мы не одиноки и проколы случаются с куда более крупными компаниями. Так с 1 июня 2010 г. перестал запускаться Corel X4. На официальном форуме техподдержки дается решение проблемы: "set back the clock 1-2 months".

Отстоим свой интернет!

Создан сайт ukaz60.net для сбора подписей за отмену Указа 60, фактически уничтожающего свободный интернет в Беларуси. Просьба всем небезразличным поддержать!