15 июн. 2022 г.

How to find useless foreign keys in a database

With times, old databases tend to overgrow with unnecessary or just empty fields. Whilst regular fields are not much of a concern, those with foreign key constraints, especially in tables with millions of records, would needlessly inflate the database file and put performance penalty on every insert/update/delete operation, as appropriate index need to be updated.

For example, an index on a field that holds nothing more than NULL values over a table with 100 000 000 records has a size approximately of 600 MB.

The query below helps to spot fields with foreign keys, which contain no more than a given count of unique values (by default, the variable maxuniqvalues is set to 1 to find all fields which are empty or contain exactly one value). Additionally, the condition on minimal record count in a table in question could be set through variable minreccnt.

The result data set includes the following columns: name of the relation, number of records in the relation, name of the field, value (only the first value is shown), and a list of objects dependent on the field. The latter will help a lot if the field to be deleted later.

  EXECUTE BLOCK
  RETURNS(
    rn VARCHAR(31),
    reccnt INTEGER,
    fkfieldname VARCHAR(31),
    val INTEGER,
    dependent VARCHAR(8192)
  )
AS
  DECLARE VARIABLE minreccnt DOUBLE PRECISION = 1000000;
  DECLARE VARIABLE maxuniqvalues DOUBLE PRECISION = 1;
BEGIN
  FOR
    SELECT
      rc.rdb$relation_name,
      CAST((1 / idx.rdb$statistics) AS INTEGER),
      idxsfk.rdb$field_name,
      (SELECT
         LIST(TRIM(d.rdb$dependent_name))
         FROM rdb$dependencies d
         WHERE 
           d.rdb$depended_on_name = rc.rdb$relation_name
           AND 
           d.rdb$field_name = idxsfk.rdb$field_name)
    FROM
      rdb$relation_constraints rc
      JOIN rdb$indices idx
        ON idx.rdb$index_name = rc.rdb$index_name
      JOIN rdb$index_segments idxs
        ON idxs.rdb$index_name = idx.rdb$index_name
        AND idxs.rdb$field_position = 0
      JOIN rdb$relation_constraints rcfk
        ON rcfk.rdb$constraint_type = 'FOREIGN KEY'
        AND rcfk.rdb$relation_name = rc.rdb$relation_name
      JOIN rdb$indices idxfk
        ON idxfk.rdb$index_name = rcfk.rdb$index_name
      JOIN rdb$index_segments idxsfk
        ON idxsfk.rdb$index_name = idxfk.rdb$index_name
        AND idxsfk.rdb$field_position = 0
    WHERE
      rc.rdb$constraint_type = 'PRIMARY KEY'
      AND
      (idx.rdb$statistics > 0 
        AND idx.rdb$statistics < (1.0 / :minreccnt))
      AND
      idxfk.rdb$statistics >= (1.0 / :maxuniqvalues)
    ORDER BY
      idx.rdb$statistics ASC
    INTO
      :rn, :reccnt, :fkfieldname, :dependent
  DO BEGIN
    EXECUTE STATEMENT 
      'SELECT FIRST 1 ' || 
      :fkfieldname || 
      ' FROM ' || 
      :rn
      INTO :val;
    SUSPEND;
  END
END

13 февр. 2022 г.

Текущее состояние gdmn-nxt

В рамках gdmn-nxt сделано считывание RDB и AT таблиц и почти доделано на их основе создание полной ER модели данных. В отличие от первой попытки (предпринятой в рамках GDMN) мы используем не классы, а легковесные js объекты без ссылок внутри. Такие объекты быстро создаются, элементарно сериализуются и передаются по сети. Имея в руках ER модель мы можем:
  1. Автоматически создавать на сервере энд поинты для CRUD операций над бизнес-объектами.
  2. Автоматически создавать на клиенте UI для работы с данными (форма просмотра и диалоговое окно в терминах Гедымина).
Эти два пункта достаточно просты и мы планируем завершить их в течение нескольких дней после того, как будет готова ER модель и созданы визуальные компоненты для выбора объекта (выпадающий список, аналог TgsIBLookupCombobox) и для выбора множества объектов.

Останется добавить фильтрацию (создание пользователем произвольного фильтра, передача его на сервер для формирования и выполнения SQL запроса) и мы получаем мини Гедымин. Без макросов, складской и бухгалтерской логики, но тем не менее, уже готовое к применению в промышленных задачах.

ER Model делается максимально отвязанной от физической структуры базы данных. Т.е. в дальнейшем мы сможем заменять Firebird на другую базу данных, подключаться через специальный переходник к системам вроде 1С или даже подключаться к нескольким базам и системам одновременно.

28 янв. 2022 г.

Зависание nodejs при запуске через окно терминала Windows

Есть неприятная особенность в окне терминала Windows. Если включен режим Quick Edit (Быстрая вставка или Быстрое редактирование в русскоязычной версии интерфейса), то в определенный момент терминал может перейти в режим ожидания клавиатурного ввода от пользователя. Выйти из этого режима можно нажав любую клавишу, но пока это не будет сделано, сервер node будет висеть и не отвечать на запросы по сети.

У данной проблемы есть следующие решения:

  1. Отключить режим Quick edit в окне Properties терминала (см. скриншот ниже)
  2. Использовать другой терминал (например, git bash)
  3. Запускать nodejs через Task Scheduler операционной системы.
Дополнительная информация на Stack Overflow.

26 янв. 2022 г.

Шрифт MS Sans Serif для кирилической кодировки Win-1251

В некоторых случаях мы сталкивались с тем, что на разных версиях Windows, включая новейшую 11-ю версию, шрифт MS Sans Serif (© Microsoft 1992) поставлялся без кодовой таблицы Win-1251. Соответственно, в Гедымине не отображались некоторые меню, текст в таблицах и надписи в выпадающих списках. Скачайте и установите данный шрифт, если вы столкнулись с вышеуказанной проблемой.

20 янв. 2022 г.

Ровно в следующий четверг, 27 января, нам исполняется 28 лет! Традиционный боулинг, как обычно, в 19:00 в клубе Мэдисон. В ЧЕТВЕРГ! Будем рады видеть всех наших сотрудников! Как действующих, так и бывших.

🎳

Различие в поведении finally между Delphi и Javascript

Пришлось потратить пару дней в поисках трудновыявимой ошибки. Все дело в том, что finally работает в Delphi и NodeJS по-разному. Будьте осторожны.

Например, в Делфи, код в секции finally выполнится ПЕРЕД окончанием выполнения функции:

function someFunc;
var
tr: TIBTransaction; 
begin
tr := TIBTransaction.Create(); 
try
... 
finally
if tr.InTransaction then
tr.Commit;
tr.Free;  
end; 
end; 

В Javascript, код в секции finally (даже не смотря на наличие await) выполнится уже ПОСЛЕ того как результат функции будет передан получателю. 

export const upsertAccount: RequestHandler = async (req, res) => {
  const { client, attachment, transaction} = await setConnection();

  try {
...
  }
  finally {
    await closeConnection(client, attachment, transaction);
  }
}; 

Теперь представим такую ситуацию. На веб сервер посылается сначала запрос на изменение данных, а после его выполнения запрос на получение (перечитывание) данных. Если мы будем делать commit транзакции в секции finally, то возможна такая ситуация, когда первый запрос уже завершится и вернет результат на клиента, который, в свою очередь, выполнит второй запрос к серверу, а транзакция все еще будет не подтверждена. В этом случае клиент получит старые данные, не соответствующие тому, что находится в базе данных.

Выход в данном случае или комитить транзакцию до секции finally, или использовать мьютекс на несколько обработчиков, который не даст прочитать данные, пока не запишется транзакция, которая меняла эти данные.


31 дек. 2021 г.


Коллектив компании Golden Software поздравляет всех с наступающим Новым Годом и желает чтобы в 2022 году исполнились ваши самые заветные и смелые мечты!

14 дек. 2021 г.

За будущее беларуского софта можно не волноваться

Хочется поделиться потрясающими и воодушевляющими впечатлениями от участия в качестве ментора в открытом IT хакатоне минской школы Stembridge. Наша компания была инициатором и спонсором данного мероприятия, но вся организационная часть лежала на Stembridge. В том числе и выбор задания. Надо сказать, что первый раз увидев поставленную задачу – "E-PROFILE" – решение на тему "Как в электронном виде наглядно и удобно собирать портфолио достижений каждого ученика от 1 до 11 класса?" – у меня возникли сомнения насколько такая, по сути, прикладная задача, будет интересна ученикам 8-11 классов. Все мы привыкли к олимпиадным задачам, как к хитрым и абстрактным головоломкам, редко пересекающимся с повседневной жизнью. Тем более, что предложенные подвопросы к основной задаче: 

  • Формат ввода и хранения данных (простота и доступность с разных устройств и разных форматов)
  • Качество данных (достоверность, актуальность) • Безопасность и доступ к данным (разные уровни доступа) 
  • Визуальное оформление: панели, отчеты и т.д. 
  • Интеграция с внешней базой данных 

Больше напоминали технические требования из взрослого тендера на разработку промышленной системы. Смогут ли дети понять, что такое реляционные структуры данных и спроектировать конкретные сущности (таблицы) из задания? Какой инструментарий выберут для прототипирования пользовательского интерфейса? На какой платформе будут создавать программный код и смогут ли показать работающее решение (прототип), если на кодирование после обсуждения останется максимум 4-5 часов? 

Сомнений было много. Мне досталась команда номер 4. Две девочки, три мальчика. После вводной части началась работа по командам и тут меня ждал настоящий, в хорошем смысле, шок. После небольшого пятиминутного наставления, ребята работали полностью самостоятельно. Школьники 10-го класса смогли полностью уяснить суть задачи, понять какие данные им нужны, где их брать и как хранить, набросать эскизы интерфейса на графическом планшете и даже создать работающий прототип с фронтальной частью на React и бэк-эндом на Node. И это все менее чем за 5 часов! 

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

После достаточно длительного совещания жюри (реально трудно было выбрать победителя – абсолютно все работы были хороши и достойны), были объявлены команды, занявшие первое, второе и, команда, где мне пришлось немного побыть ментором -- третье место. 

Вне зависимости от занятого места каждый из участников остался в выигрыше получив ценный опыт, а я получил уверенность, что за будущее беларуского софта можно не волноваться. Новое поколение уже на подходе! 

PS: чуть позже мы разместим здесь видео с хакатона.

30 нояб. 2021 г.

Открытый хакатон 11 декабря для учащихся 8-11 классов

Компания Golden Software выступила спонсором открытого хакатона E-PROFILE, проводимого школой Стембридж. К участию приглашаются ученики 8-11 классов, а также взрослые эксперты для менторинга, сопровождения и качественного судейства представленных проектов.

Время: суббота 11 декабря 2021 года, с 9.30 до 19.00.

Место: онлайн. Хакатон будет проводиться с использованием платформ Zoom и GoogleMeet. Все ссылки и необходимые документы будут высланы участникам накануне мероприятия на электронные адреса, указанные в регистрационной форме.

Участники: учащиеся 8-11 классов, прошедшие регистрацию. Количество участников ограничено (на 55 заявках закрывается реегистрация)

Тематика: на хакатоне мы посоревнуемся в поиске лучшего решения на тему “Как в электронном виде наглядно и удобно собирать портфолио достижений каждого ученика от 1 до 11 класса?”

Подвопросы:

  • Формат ввода и хранения данных (простота и доступность с разных устройств и разных форматов)
  • Качество данных (достоверность, актуальность) Безопасность и доступ к данным (разные уровни доступа)
  • Визуальное оформление: панели, отчеты и т.д.
  • Интеграция с базами данных

Ссылка на Положение и регистрационную форму.

Ссылка на регистрацию для взрослых волонтеров в роли экспертов, менторов и судей.

26 нояб. 2021 г.

Конфигурация небольшого сервера для базы данных Гедымина

На днях один клиент обратился с просьбой порекомендовать конфигурацию сервера под базу данных размером в районе 50 Гб и количеством одновременных подключений 25+. Думаю такая рекомендация может быть интересна и другим нашим клиентам, а также как исторический материал, который через некоторое время позволит сравнить цены и оценить скорость развития вычислительной техники.

Курс доллара на момент написания где-то в районе 2.5 руб за 1 USD.

  1. Память. Ставьте 256 ГБ самой быстрой DDR4, которую будет поддерживать материнская плата. Это на вырост. Если 256 Гб дорого, то никак не меньше 128 Гб. Планка на 32 Гб стоит сейчас где-то в районе 400 руб.
  2. Процессор AMD Ryzen 9 5900X (12 ядер, ~1500 руб) или 5950X (16 ядер, ~2200 руб).
  3. 4 планки NVME по 1 Tb. Что-нибудь вроде SSD Samsung 980 Pro 1TB (по 550 руб за штуку). Из них собрать два зеркала RAID 1. Одно использовать для размещения операционной системы, темп каталога и папки с архивами бд, а второе -- для размещения рабочего файла базы данных.
  4. Материнская плата с поддержкой всего вышеперечисленного (в т.ч. PCI Express 4.0). Сеть желательно 10 Gbit Ethernet до центрального свитча. Видео встроенное в материнскую плату или самое простое. Монитор можно б/у-шный тоже самый простой.
  5. Корпус можно самый обычный брать. Блока питания на 600 W хватит вполне.
  6. Надежный бесперебойник.
На вскидку, суммарная стоимость будет:

8 * 400 + 1500 + 550 * 4 + 600 + 300 + 400 = 8200, округленно -- 9000 руб.

Этой техники хватит без проблем, по производительности, на 5 ближайших лет.

22 мая 2021 г.

Смена хостинга для нашего сайта

Пока мы осваиваемся на новом хостинге могут наблюдаться небольшие перебои в работе сайта. Если при обращении к сайту возникает ошибка, очистите сохраненные cookies. Для этого откройте меню, кликнув по пиктограммке слева от имени сайта в адресной строке браузера и вызовите соответствующую команду.

https:// версия сайта тоже доступна, но пока не сделана основной. Надо еще поискать по коду все ссылки на незащищенный протокол и поменять их.

Если заметите ошибки в работе сайта, будем признательны обратной связи на адрес support[at]gsbelarus.com.

28 апр. 2021 г.

Охота на утечки памяти

В отладочную версию gedemin.exe и новейшую версию класса TCreator добавлено расширенное логирование:

  1. Транзакции. Логируется старт и завершение транзакции. Показывается количествоактивных транзакций в данный момент времени. 
  2. IBSQL. Логируется выполнение запроса. Для SELECT запросов логируется закрытие. Показывается количество открытых на чтение запросов.
  3. Designer. Логируется создание и удаление объекта. Показывается количество объектов в памяти.
  4. TCreator. Логируется создание и удаление экземпляра класса. Показывается количество TCreator  в памяти.

Обратите внимание, что в Гедымине скрипт-функции внутри диалогового окна зашитого в платформу выполняются в рамках отдельного модуля и внутри него будет идти свой отсчет экземпляров TCreator.