Вопрос

Cделан запрос в базу данных из клиентского модуля для получения системной настройки: 

this.Terrasoft.SysSettings.querySysSettingsItem("PsMaximumProgramsCount", function(value) {
	countSettings = value;
}, this);

Получены данные из БД отфильтровав их и сравнив с полученным значением из системной настройки ранее, и если значение выпадающего списка periodicity  равно "Ежедневно" и количество записей в базе больше чем системной настройке - срабатывает валидация на поле и всплывающее уведомление при попытке сохранения:

message - сообщение для поля валидации;

periodicity  - выпадающий список (словарь) в котором есть значение "Ежедневно";

countSettings  - ранее полученное значение системной настройки;

concertProgramsCount - количество записей в таблице;

var periodicity = "";
if (this.get("PsPeriodicity")) {
	periodicity = this.get("PsPeriodicity").displayValue;
}
var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
	rootSchemaName: "PsConcertPrograms"
});
esq.addColumn("PsPeriodicity.Name", "PsPeriodicityName");
var esq1Filter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
	"PsPeriodicity.Name", "Ежедневно");
esq.filters.add("esq1Filter", esq1Filter);
esq.getEntityCollection(function(result) {
	var message = "";
	if (result.success) {
		var concertProgramsCount = result.collection.collection.length;
		if (periodicity === "Ежедневно" && concertProgramsCount <= countSettings ) {
			message = this.get("Resources.Strings.PsFewFreeConcertHalls").replace("NNN", countSettings);
		}
	}
	return message;
}, this);

Вывод валидации для поля и при сохранении страницы:

concertHallsValidator: function(message) {
	var invalidMessage = message;
	return {
		fullInvalidMessage: invalidMessage,
		invalidMessage: invalidMessage
	};
}

Проблема в том что по отдельности все работает, но когда вместе - вступает в дело асинхронность и все идет не по очереди, а если использую через callback тогда застреваю на замыкании.

Спасибо всем кто окажет помощь в решении проблемы.

У меня такой же вопрос

7 комментариев
Лучший ответ

Prime Source,

нет. стоп. я думал вы прогоняете esq в onEntityInitialized, а потом используете this.$PeriodValidationMessage для проверки. тогда такие варианты:

1) на изменение поля PsPeriodicity запускаете concertHallsValidator. Изменяете this.addColumnValidator("CreatedOn", this.MessageValidator);
2) Используете asyncValidate (вроде так называется метод)

И уберите return. Ну не используется он в асинхронных функциях)

немного не понимаю смысла return из async функции, поэтому вариант такой:

в attributes добавляете 

"PeriodValidationMessage": {
	dataValueType: 1,
	value: ""
}

esq:

var periodicity = "";
if (this.get("PsPeriodicity")) {
	periodicity = this.get("PsPeriodicity").displayValue;
}
var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "PsConcertPrograms" });
esq.addColumn("PsPeriodicity.Name", "PsPeriodicityName");
esq.filters.addItem(esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "PsPeriodicity.Name", "Ежедневно"));
esq.getEntityCollection(function(result) {
	if (result.success) {
		var concertProgramsCount = result.collection.collection.length;
		//считывание сист. настройки
		Terrasoft.SysSettings.querySysSettingsItem("PsMaximumProgramsCount", function(countSettings) {
			//сравнение
			if (periodicity === "Ежедневно" && concertProgramsCount <= countSettings ) {
				this.$PeriodValidationMessage = this.get("Resources.Strings.PsFewFreeConcertHalls").replace("NNN", countSettings);
			}
 
		}, this);
	}
}, this);

валидация

concertHallsValidator: function(message) {
	var invalidMessage = this.$PeriodValidationMessage;
	return {
		fullInvalidMessage: invalidMessage,
		invalidMessage: invalidMessage
	};
}

 

Добрый день,

Каждый борется с асинхронностью своими средствами :)

Как вариант, можно вложить одно в другое: выполнять запросы по очереди, по мере получения ответа из БД. Например перенести вашу логику с esq запросом в колбэк системной настройки.

Тёскин Дмитрий Валерьевич,

 

Пробовал, тогда return возвращает поздно ответ

concertHallsValidator:  function(){
	var periodicity = "";
	if (this.get("PsPeriodicity")) {
		periodicity = this.get("PsPeriodicity").displayValue;
	}
	this.Terrasoft.SysSettings.querySysSettingsItem("PsMaximumProgramsCount", function(countSettings) {
		var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
			rootSchemaName: "PsConcertPrograms"
		});
		esq.addColumn("PsPeriodicity.Name", "PsPeriodicityName");
		var esq1Filter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
			"PsPeriodicity.Name", "Ежедневно");
		esq.filters.add("esq1Filter", esq1Filter);
		esq.getEntityCollection(function(result) {
			var invalidMessage = "";
			if (result.success) {
				var concertProgramsCount = result.collection.collection.length;
				if (periodicity === "Ежедневно" && concertProgramsCount > countSettings ) {
					invalidMessage = this.get("Resources.Strings.PsFewFreeConcertHalls").replace("NNN", countSettings);
				}
			}
			return invalidMessage;
		}, this);
	}, this);
},
setValidationConfig: function() {
	this.callParent(arguments);
	this.addColumnValidator("PsPeriodicity", this.concertHallsValidator);
}

 

Варфоломеев Данила,

Асинхронность не дает

methods: {
	concertHallsValidator:  function(callback){
		var periodicity = "";
		if (this.get("PsPeriodicity")) {
			periodicity = this.get("PsPeriodicity").displayValue;
		}
		var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "PsConcertPrograms" });
		esq.addColumn("PsPeriodicity.Name", "PsPeriodicityName");
		esq.filters.addItem(esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "PsPeriodicity.Name", "Ежедневно"));
		esq.getEntityCollection(function(result) {
			if (result.success) {
				var concertProgramsCount = result.collection.collection.length;
				//считывание сист. настройки
				Terrasoft.SysSettings.querySysSettingsItem("PsMaximumProgramsCount", function(countSettings) {
					//сравнение
					if (periodicity === "Ежедневно" && concertProgramsCount <= countSettings ) {
						this.$PeriodValidationMessage = this.get("Resources.Strings.PsFewFreeConcertHalls").replace("NNN", countSettings);
					}
					return callback.call(this);
				}, this);
			}
		}, this);
	},
	MessageValidator: function() {
		var invalidMessage = this.$PeriodValidationMessage;
		return {
			fullInvalidMessage: invalidMessage,
			invalidMessage: invalidMessage
		};
	},
	setValidationConfig: function() {
		// Вызывает инициализацию валидаторов родительской модели представления.
		this.callParent(arguments);
		this.addColumnValidator("CreatedOn", this.concertHallsValidator(this.MessageValidator));
	}
},
			}

 

Prime Source,

нет. стоп. я думал вы прогоняете esq в onEntityInitialized, а потом используете this.$PeriodValidationMessage для проверки. тогда такие варианты:

1) на изменение поля PsPeriodicity запускаете concertHallsValidator. Изменяете this.addColumnValidator("CreatedOn", this.MessageValidator);
2) Используете asyncValidate (вроде так называется метод)

И уберите return. Ну не используется он в асинхронных функциях)

Варфоломеев Данила,

 

Спасибо большее, помогло отлично asyncValidate. Раньше не знал что этот метод. Вод такой код заработал отлично:

asyncValidate: function(callback, scope) {
	this.callParent([function(response) {
		if (!this.validateResponse(response)) {
			return;
		}
		Terrasoft.chain(
			function(next) {
				this.validateConcertHalls(function(response) {
					if (this.validateResponse(response)) {
						next();
					}
				}, this);
			},
			function(next) {
				callback.call(scope, response);
				next();
			}, this);
	}, this]);
},
validateConcertHalls: function(callback, scope) {
	Terrasoft.SysSettings.querySysSettingsItem("PsMaximumProgramsCount", function(countSettings) {
		var periodicity = "";
		var result = {success: true};
		if (this.get("PsPeriodicity")) {
			periodicity = this.get("PsPeriodicity").displayValue;
		}
		var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "PsConcertPrograms" });
		esq.addColumn("PsPeriodicity.Name", "PsPeriodicityName");
		esq.filters.addItem(esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, 
			"PsPeriodicity.Name", "Ежедневно"));
		esq.getEntityCollection(function(response) {
			if (response.success && periodicity === "Ежедневно" && (!this.isAddMode() && 
				response.collection.getCount() > countSettings) || (this.isAddMode() && 
				response.collection.getCount() >= countSettings)) {
					result.message = this.get("Resources.Strings.PsFewFreeConcertHalls").replace("NNN", countSettings);
					result.success = false;
			}
			callback.call(scope || this, result);
		}, this);
	}, this);
}

 

Prime Source,

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

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Здравствуйте, в детали [Амбулаторная карточка] есть поле [ФИО Врача] и поле [Специализация Врача]. Нужно вывести [Специализацию Врача] из установленного поля [Фио Врача]. Врач-это контакт и у него уже есть поле Специализации. Везде описывают кейс с числовыми значениями, но вывод из БД нигде нет. Буду очень благодарен, если подскажите.

У меня такой же вопрос

4 комментария
Лучший ответ

Все можно проще сделать укажите чтоб для доктора вычитывались колонки ФИО и Специлизация и используйте их!

"UsrDoctor": {
  lookupListConfig: {
   columns: ["FIO","UsrDoctorsSpecialization"]
  }
 },

После єтого можно обращатся к полю как UsrDoctor.UsrDoctorsSpecialization

Если я правильно понял, то надо сделать вот так:

attributes: {
//Здесь мы "смотрим" внутрь справочного поля [UsrDoctor], которое ссылается на раздел [Контакты]
//и ищем там специализацию [UsrDoctorsSpecialization]
 "UsrDoctor": {
  lookupListConfig: {
   columns: ["UsrDoctorsSpecialization"]
  }
 },
//Здесь мы вызываем метод, который будет устанавливать специализацию, когда пользователь 
//внесет изменения в поле [UsrDoctor]
 "UsrDoctorsSpecialization": {
  dependencies: [
   {
    columns: ["UsrDoctor"],
    methodName: "setDoctorsSpecializtion"
   }
  ]
 }
},
methods: {
//собственно метод, который устанавливает специализацию в нужное поле
//условие можно и изящней написать. Сделал так, чтобы было понятно.
 setDoctorsSpecializtion: function() {
  var doctor = this.get("UsrDoctor");
  if (doctor) {
   if (doctor.UsrDoctorsSpecialization) {
    this.set("UsrDoctorsSpecialization", doctor.UsrDoctorsSpecialization);
   }
   else {
    this.set("UsrDoctorsSpecialization", null);
   }
  } 
  else {
   this.set("UsrDoctorsSpecialization", null);
  }
 }
},

 

Все можно проще сделать укажите чтоб для доктора вычитывались колонки ФИО и Специлизация и используйте их!

"UsrDoctor": {
  lookupListConfig: {
   columns: ["FIO","UsrDoctorsSpecialization"]
  }
 },

После єтого можно обращатся к полю как UsrDoctor.UsrDoctorsSpecialization

Григорий Чех,

Вау, почему в документации еще нет этого способа?:)

Есть:

lookupListConfig — свойство, отвечающее за свойства поля-справочника. Подробнее об использовании данного параметра можно узнать из статьи "Применение фильтрации к справочным полям". Это конфигурационный объект, который может содержать в себе следующие опциональные свойства:

  • сolumns — массив имен колонок, которые будут добавлены к запросу дополнительно к колонке Id и первичной для отображения колонке.
  • orders — массив конфигурационных объектов, которые определяют сортировку данных при отображении.
  • filter — метод, возвращающий объект класса Terrasoft.BaseFilter или его наследника, который, в свою очередь, будет применен к запросу. Не может использоваться совместно со свойством filters.
  • filters — массив фильтров (методов, возвращающих коллекции класса Terrasoft.FilterGroup). Не может использоваться совместно со свойством filter.
Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Приветствую, уважаемые коллеги!

В данной статье я хочу привлечь внимание не только разработчиков, но и партнёров Террасофт и их представителей.

Сегодня я расскажу Вам о преимуществах и выгодах использования приложения для оперативной проверки структуры базы данных (далее - БД) на корректность (https://marketplace.terrasoft.ru/app/database-structure-check).

Проблематика.

После накатывания нового функционала на тестовую среду могут появиться ошибки структуры БД. Их особенности:

  • не всегда очевидны.
  • разработчиков может сбивать с толку тот факт, что на рабочей среде всё работает, а на тестовой – нет.
  • поиск и устранение может занять длительное время.

Всё это снижает эффективность разработки/обслуживания, приводит к дополнительным расходам ресурсов. 

После накатывания на промышленную среду могут также появиться ошибки. Они имеют ту же природу, но масштаб их разрушительного действия уже выше, т.к. это промышленная среда, соответственно, плюс к проблемам выше:

  • падает надёжность системы.
  • повышается вероятность аварии.

Особенно это актуально, когда «окно» для обновления промышленной среды очень небольшое. Чем больше проект в плане доработок, тем больше ошибок структуры БД может возникать.

При использовании приложения все эти проблемы можно успешно решить!

Целевая аудитория.

Обращаю внимание партнёров Terrasoft: приложение предназначено для среднего и крупного бизнеса. То есть, основные преимущества от его использования получает именно клиент. Приложение универсально и подойдёт практически всем клиентам, у которых есть потребность в доработке базовых продуктов.

Степень необходимости приложения может варьироваться. Если в ходе выяснения потребностей выясняется, что:

  1. будет большой проект (или уже есть) со сложными связями между сущностями системы.
  2. есть потребность в максимальной надёжности.
  3. у клиента только небольшие «окна» для обновления промышленной среды.
  4. есть потребность в повышении эффективности разработки и обслуживания (клиент хочет как можно скорее получить готовую систему в пользование).
  5. есть потребность в повышении устойчивости к авариям системы.

- это всё покажет рост степени необходимости приложения. Я настоятельно рекомендую устанавливать приложение всем клиентам в случае, если имеет место хотя бы один пункт выше.

Выгоды.

Какие выгоды получит клиент от использования приложения? Как правило, это выгоды в долгосрочной перспективе. Клиент:

  1. получит дополнительную меру повышения надёжности системы.
  2. сэкономит ресурсы на обнаружение ошибок структуры БД.
  3. обеспечит повышение эффективности разработки и обслуживания системы.
  4. обеспечит повышение устойчивости системы к авариям из-за ошибок структуры БД.

Есть также выгоды для разработчиков, облегчающие некоторые аспекты разработки/сопровождения. Разработчики: 

  1. смогут пользоваться самым рациональным решением для проверок структуры БД, которое не имеет аналогов.
  2. смогут пользоваться всем функционалом приложения в один клик.
  3. смогут проверять структуру БД на корректность в течение нескольких секунд.
  4. смогут оперативно выявлять отсутствующие таблицы и/или их колонки, обнаруживать несоответствия типов полей.
  5. после проверки структуры БД смогут понять, для каких объектов необходимо произвести повторное обновление структуры БД.
  6. после успешного анализа, будут точно знать, что БД целевой среды содержит все требуемые системой таблицы/поля, и что типы всех полей всех таблиц правильные.

Преимущества.

  1. Поиск ошибок структуры БД. Приложение выявляет отсутствующие таблицы и/или их колонки, а также обнаруживает несоответствия типов полей.
  2. Повышение надёжности. Использование приложения повышает надёжность системы за счёт минимизации времени, в течение которого в структуре БД есть ошибки.
  3. Экономия ресурсов. Использование дополнения сокращает расходы на обнаружение ошибок структуры БД. В ряде случаев очень серьёзно сокращает расходы.
  4. Подтверждение целостности. После успешного анализа, специалист будет точно знать, что база данных целевой среды содержит все требуемые системой таблицы/поля, и что типы всех полей всех таблиц соответствуют требуемым типам.
  5. Повышение эффективности разработки и обслуживания. Это происходит за счёт экономии ресурсов при использовании приложения, а также за счёт ускорения обнаружения ошибок структуры БД.
  6. Простота использования. Запуск функционала в один клик.
  7. Быстрая скорость работы. Проверка структуры БД в течении нескольких секунд.
  8. Простая и удобная форма отчёта приложения. После проверки, в случае наличия ошибок, специалисту будет предоставлено подробное информационное сообщение. Разработчик сразу поймёт, для каких объектов необходимо произвести повторное обновление структуры БД.
  9. Локализация на английский язык. Поддержка не только русского языка, но и английского.
  10. Самое рациональное решение для проверок структуры БД. На самом деле, можно проверить вручную, но это дольше (просмотреть все разделы, вкладки, детали, а также проверить работоспособность всего разработанного функционала) и не всегда возможно проверить вообще всё. Зачастую такого количества времени просто нет. 
  11. Уникальность. Инструмент для проверки структуры БД не имеет аналогов на маркетплейс.
  12. Смешная цена. За год использования, то есть возможно продление на следующий год. Продлевать нет смысла только если разработка/обслуживание полностью завершены. Экспертные продажи.
  13. Повышение устойчивости системы к авариям, вызванным ошибками структуры БД. Использование приложения позволяет обнаружить ошибки БД сразу же после обновления целевой среды, после чего сразу предпринять действия для исправления найденных ошибок.

Совместимость.

Приложение совместимо со всеми продуктами на платформе bpm’online (с версии 7.11, на остальных нужно тестировать, но скорее всего работать будет).
В данный момент не поддерживается работа на системах, для которых используется СУБД Oracle.

Большое спасибо всем, кто дочитал до конца!

Буду рад любым предложениям по совершенствованию продукта!

С уважением, Сергей Кузнецов.

Поделиться

1 комментарий

yes

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

В какой то момент пропали настройки журнала изменений по контакту.
Как можно отследить изменение настроек аудита? Кто, когда?

У меня такой же вопрос

4 комментария

Егор, добрый день!

Обычно такие задачи решаются с помощью самого журнала аудита (не журнала изменений). Но сейчас в системе не логируется изменение настроек журнала изменений (я создала соответствующую идею в беклоге профильной команды). Список логируемых операций можно посмотреть тут: https://academy.terrasoft.ru/documents/studio/7-12/razdel-zhurnal-audita

В качестве обходного решения можно сделать следуюшее:

1. Для анализа текущей ситуации проанализировать логи приложения (там должны быть видны соответсвующие запросы) и сравнить с данными по сессиям пользователей.

2. На будущее реализовать собственный тригер на уровне БД, который будет писать в лог, если кто-то будет менять настройки журнала изменений.

Старун Юлия,
спасибо за развернутый ответ!

Юлия, можете еще подсказать на какую таблицу вешать триггер чтобы отследить изменение настроек журнала изменений?
Настройка - по каким полям ведется логирование в таблицу SysContactLog.

Егор, как оказалось, все не так просто (как это бывает). Настроки журнала хранятся непосредственно в метаданных таблицы, которая логируется. Причем в слабочитаемом виде. Система умеет их парсить. Например, открыв в конфигурации метаданные логируемого объекта вы можете увидеть читабельный текст со свойствами всех колонок объекта:

        {
          "UId": "736c30a7-c0ec-4fa9-b034-2552b319b633",
          "Name": "Name",
          "CreatedInSchemaUId": "11ab4bcb-9b23-4b6d-9c86-520fae925d75",
          "ModifiedInSchemaUId": "4cbdc6f3-625d-4639-92bf-bb19d4c9d58e",
          "CreatedInPackageId": "66e9e705-64b4-4dda-925e-d1e05a389eb6",
          "DataValueTypeUId": "ddb3a1ee-07e8-4d62-b7a9-d0e618b00fbd",
          "RequirementType": 1,
          "IsTrackChangesInDB": true,
          "IsLocalizable": true
        },

Но вот на уровне базы данных это уже хранится в колонке MetaData таблицы SysSchema в не таком удобном виде. Там следует искать код Е16, чтобы понять, колонка с каким UID логируется:

Таким образом, триггер нужно вешать на таблицу SysSchema на колонку MetaData по тому объекту, который вы хотите отследить. И сохранять весь текст метаданных, а потом уже анализировать его вручную. Наверное, можно даже посмотреть, какой запрос отправляет система в БД при открытии страницы настроек журнала изменений - там наверняка есть встроенные механизмы парсинга этих данных.

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

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день, коллеги!
Есть разработческая площадка, развернутая на БД клиента с неактуальными данными, на ней ведутся все доработки в свой пакет и фиксируются в хранилище. Также есть "пустая" продуктивная площадка, на которую все изменения применяются. Кроме того, необходимо настроить права доступа, интеграцию с АД, прописать орг структуру. После окончания всех работ нужно перенести все изменения на актуальную базу клиента. Все доработки перенести с помощью хранилища не проблема, но права доступа, интеграция с АД, пользователи, орг структура, настройки почтового ящика хранятся в БД. Поэтому при переносе эти настройки можно потерять. В связи с этим вопрос: есть ли способ переноса данных с одной базы на другую?

У меня такой же вопрос

2 комментария

Добрый день, Елена.

Права доступа, настройки интеграции с LDAP, организационную структуру, настройки почтового ящика мы рекомендуем настраивать вручную непосредственно на актуальной среде. В случае переноса настроек, есть вероятность частичной неработоспособности функциональности. Например, при переносе настроек почтовых ящиков синхронизация почты не будет работать, так как при переносе не будут созданы job'ы.

Управление пользователями по своей логике и структуре сильно отличается от других объектов в системе, и кроме очевидных сложностей, с которыми Вы столкнулись может произойти дублирование данных в разделе, что в свою очередь может привести к полной или частичной неработоспособности системы.

Перенос настроек интеграции с LDAP также приведет к тому, что синхронизация не будет запущена.

В данной ситуации правильно будет выполнить все настройки вручную на актуальной БД.

"Мария Ватулина" написал:

Добрый день, Елена.

Права доступа, настройки интеграции с LDAP, организационную структуру, настройки почтового ящика мы рекомендуем настраивать вручную непосредственно на актуальной среде. В случае переноса настроек, есть вероятность частичной неработоспособности функциональности. Например, при переносе настроек почтовых ящиков синхронизация почты не будет работать, так как при переносе не будут созданы job'ы.

Управление пользователями по своей логике и структуре сильно отличается от других объектов в системе, и кроме очевидных сложностей, с которыми Вы столкнулись может произойти дублирование данных в разделе, что в свою очередь может привести к полной или частичной неработоспособности системы.

Перенос настроек интеграции с LDAP также приведет к тому, что синхронизация не будет запущена.

В данной ситуации правильно будет выполнить все настройки вручную на актуальной БД.


Мария, спасибо за ответ!

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Здравствуйте!

Подскажите, как можно осуществить проверку наличия таблиц и их колонок БД по именам, используя EntitySchemaManager в веб-сервисе? Чтобы проверить перед внесением изменений в БД.

У меня такой же вопрос

2 комментария

В Terrasoft 3.Х нет механизма EntitySchemaManager. Там всё устроено иначе.

"Зверев Александр" написал:

В Terrasoft 3.Х нет механизма EntitySchemaManager. Там всё устроено иначе.


Понял. Спасибо.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день.
Подскажите за счет чего увеличивается обьем базы данных? База Террасофта находится на отдельном сервере и весит на сегодня порядка 100ГБ.
Версия террасофта - 3.3.1.148
БД - Файерберд
Заранее спасибо, за помощь.

У меня такой же вопрос

2 комментария

Часто это случается из-за пустого места в таблицах. Необходимо проводить переиндексацию таблиц и выполнять операцию srink на базе SQL. Я так добилась двукратного уменьшения базы.
Как все это правильнее сделать , Вам подробнее может помочь техподдежка.

Кроме этого у меня в базе зависали неудаленные файлы (после того, как объект к которому они были привязаны, удалялись сами файлы из базы не удалялись). Это я вычищала скриптами.

"Бучковский" написал:Подскажите за счет чего увеличивается обьем базы данных

Смотрите размеры таблицы tbl_MailMessages и tbl_Files
Если пользоваться ibexpert, то это меню Services-Database Statistics.
Основной рост базы данных за счет прикрепления писем и хранения файлов в базе данных.

Плюс, как написала Виктория, из-за пустого места в таблицах - подробнее здесь

"Тихенко Виктория" написал:выполнять операцию srink на базе SQL

Для firebird операция shrink не существует. Делается бэкап базы и ее восстановление. В результате свободное место будет реорганизовано.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

В процессе администрирования базы данных возникла необходимость определить причину возникновения ошибки. Определенный объём информации импортируется в базу данных, с которым далее пользователи работают. В процессе заполнения определенного набора полей автоматически высчитывалась итоговая сумма в поле «Итого». Но в определённый промежуток времени использования продукта начали появляться ошибки, связанные с несоответствием значения поля «Итого» сумме полей из которых оно вычисляется («Сумма покупки», «Наценка», «Сбор» и т.д.). Так как ошибку не получалось явно повторить, необходимо было разработать механизм для решения данной проблемы.

Естественно самой реальной и первой причиной возникновения такой ошибки приходила идея о сбоях в работе событий полей окна редактирования (то есть значения в полях изменялись, а события данных полей(-я) не срабатывали).

В основу решения было положено создание двух таблиц в базе данных для ведения логов, что происходят с записью набора данных. Первая таблица WindowLog, а вторая TriggerLog.

Первая таблица WindowLog включает в себя поля «Дата создания»(CreatedOn), «Идентификатор записи» (RecordID), «Ответственный» (WindowsUser), «Имя поля породившего событие»(FieldName), «Итого» и поля из которых оно вычисляется («Сумма покупки», «Наценка», «Сбор» и т.д.). Для наполнения таблицы было использованы события невизуального компонента окна dlData: dlDataOnDatasetDataChange, dlDataOnDatasetBeforePost и dlDataOnDatasetAfterPost. В скрипте в событиях была создана функция, которая формировала SQL запрос к таблице WindowLog базы данных с фиксацией информации по указанным полям на момент срабатывания события.

Запрос:

INSERT INTO WindowLog (*набор полей*)
SELECT (*набор полей*) -- Dataset('поле1'), Dataset('поле2'), Dataset('поле2')

Вторая таблица TriggerLog включает в себя поля «Дата создания»(CreatedOn), «Идентификатор записи» (RecordID), «Состояние» (до изменения записи и после), «SystemUser», «Итого» и поля из которых оно вычисляется («Сумма покупки», «Наценка», «Сбор» и т.д.). Для заполнения данной таблицы был создан триггер на инструкцию UPDATE проблемной таблицы с двумя запросами вставки значений в таблицу. В одном запросе вставлялись значения до изменений, а во втором после.

Запрос №1:

INSERT INTO TriggerLog (*набор полей*)       
SELECT (*набор полей*)
FROM deleted

Запрос №2:

INSERT INTO TriggerLog (*набор полей*)       
SELECT (*набор полей*)
FROM inserted

Результатом использования данного решения на основе анализа таблицы WindowLog было установлено, что срабатывают все события окна редактирования, влияющие на вычисление значения поля «Итого». В процессе использования окна редактирования и после сохранения записи значения поля «Итого» были корректны.

Проанализировав записи в таблице TriggerLog было установлено, что в результате выполнения инструкции UPDATE было внесено некорректное значение. Сопоставив даты создания записей в таблице TriggerLog и WindowLog было установлено, что инструкция UPDATE была вызвана не в результате манипуляций с окном редактирования, а иным источником. На основании поля «SystemUser» таблицы TriggerLog было установлено что изменения были внесены с помощью импортера данных.

Таблицу TriggerLog возможно расширить, добавив в нее поля, которые помогут ускорить процесс обнаружение источника изменений записи базы данных. Список дополнительных полей может выгладять следующим образом: ApplicationName, LoginName, HostName.

PS: Принимаю предложения на доработку вашей конфигурации!!! Для более детальной информации можно связаться по следующему e-mail адресу: providnui@ukr.net !!!

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

Всем удачи в этом не легком процессе!!!

У меня такой же вопрос

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Многие из нас пользуются бесплатными версиями MS SQL Server, которые, как вы понимаете, имеют ограничение на размер базы данных.
Рано или поздно, у Вас появится сообщение примерно такого характера :

ошибка сохранения

Это означает, что вы полностью использовали бесплатно предоставленное вам место.
Как показывает практика, то самой ресурсоемкой таблицей в базе данных является таблица tbl_MassMail, из-за большого количества корреспонденции в базе данных.

Для того, чтоб определить сколько места занимает каждая из таблиц базы данных вы можете использовать скрипт :

/*
** For update free space uncomment follow --, N'TRUE'
*/


SET nocount ON

IF NOT object_id('tempdb..[#space]') IS NULL DROP TABLE [#space]

declare @TABLE [sysname]

CREATE TABLE [#space] (
        [name] [nvarchar](128),
        [rows] [char](11),
        [rows_int] [int],
        [reserved] [varchar](18),
        [DATA] [varchar](18),
        [data_int] [int],
        [index_size] [varchar](18),
        [unused] [varchar](18),
        [unused_int] [int]
)

declare [c] cursor FOR
SELECT name
FROM sysobjects
WHERE type = N'U'
ORDER BY name

open [c]

while (1 = 1)
begin
        fetch next FROM [c] INTO @TABLE
       
        IF @@fetch_status = -1 break
        IF @@fetch_status = -2 continue

        INSERT INTO [#space] ([name], [rows], [reserved], [DATA], [index_size], [unused])
        exec sp_spaceused @TABLE , N'TRUE'
end

close [c]
deallocate [c]

UPDATE [#space]
SET [data_int] = cast(REPLACE([DATA], N' KB', N'') AS [int]),
[unused_int] = cast(REPLACE([unused], N' KB', N'') AS [int]),
[rows_int] = cast([rows] AS [int])

SELECT * FROM [#space]
ORDER BY --rows_int desc
[data_int] DESC

SELECT cast(sum([unused_int]) AS varchar) + ' KB' AS [unused] FROM [#space]

Обращаю ваше внимание, что скрипт дает информацию о занимаемом месте каждой таблицей в базе данных, но не избавляет вас от оповещения, которое показано выше.
Действия, которые вы будете принимать далее, зависят только от вас, одним из вариантов есть заказ лицензий на использование MS SQL Server.

Поделиться

1 комментарий

Я бы еще советовал обращать внимание на колонку index_size - т.к. нередко индексы занимает львиную часть места в БД.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Коллеги, добрый день!

Вопрос: есть ли какая-то объективная причина того, что в БД террасофта ни в одной таблице абсолютно не используются кластерные индексы?

У нас система еле шевелится, при том что очень мощный сервер БД, всего около 150 пользователей, таблицы не сказать что очень огромные (десятки-сотни тыс. записей)... кроме таблиц логов (миллионы-десятки миллионов записей) :)
В общем производительность очень низкая.

В рамках нашего проекта вопрос построения индексов либо не был запланирован вообще либо был проигнорирован... Единственные индексы, которые построены - некластерные индексы по внешним ключам и по первичному ключу.

Спасибо!

У меня такой же вопрос

9 комментариев

Здравствуйте,
Так сложилось исторически, что для для MSSQL 2000 в общем случае некластерный индекс является оптимальным, так как в Terraosft 3.X для первичных ключей и внешних ключей используются GUID. В этом случае, если включить кластерные индексы, они будут постоянно перестраиваться, т.к. при вставке записей мы всегда получаем случайное значение GUID и для сохранения упорядоченного вида, новую запись нужно вставить в середину индекса.

Для MSSQL 2008, при использовании последовательных GUID, кластерный индекс будет более производительным. В новых версиях мы проанализируем возможность использования таких индексов для MSSQL 2008.

Алексей,

А как на счет использования "разреженных" индексов, в которых FillFactor < 100 (например 60-80)?

Или использование NEWSEQUENTIALID() вместо NEWID()?

Или введения кластерного индекса не связанного с первичным ключем (например, введение поля типа BigInt с автоинкрементом, либо выделение группы полей по которым возможно построить уникальный индекс, например для контрагента - дата создания, наименование, + может быть ИНН, ОГРН)?

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

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

Тут же возможно возникнут вопросы по сбору статистики для полей как входящих в индексы так и не входящих в них.

Здравствуйте,
1) Генерация самих GUID в Terrasoft 3.X происходит на уровне приложения (используется внутренний генератор Connector.GenGUID()), это дает возможность использовать значения идентификаторов, до их фактической вставки в таблицу, для того что бы использовать последовательную генерацию идентификаторов, необходимо править бинарные файлы, и менять логику построения на генерацию последовательных идентификаторов.

2) Если Вы имеете в виду, замену uniqueidentifier на BigInt, в Terrasoft в качестве первичных ключей, то боюсь Вас разочаровать, многие вещи в конфигурации заточены под использования типа GUID.
В качестве оптимизации вы можете построить группы полей, по которым чаще всего проводиться фильтрация/поиск, и создать кластерный индекс, это действительно может повысить производительность
Последовательные GUID в нашем случае также противоречат репликации – т.к. ключи могут повторяться.

Для начала следует оптимизировать запросы, с которыми в Вашей компании наиболее часто работают.
Для этого выловите сам запрос который идет в БД, SQL Profiler’ом и дальше работу стоит вести по плану выполнения (http://www.mssqltips.com/sqlservertip/1856/sql-server-query-execution-p…)
1

Рассмотрение возможностей оптимизации коробочного продукта, с учетом возможностей SQL Server 2008, запланировано на следующую неделю.

Спасибо, Алексей.

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

"Яворский Алексей" написал: Яворский Алексей 2 апреля 2012 – 15:48

Здравствуйте,
Так сложилось исторически, что для для MSSQL 2000 в общем случае некластерный индекс является оптимальным, так как в Terraosft 3.X для первичных ключей и внешних ключей используются GUID. В этом случае, если включить кластерные индексы, они будут постоянно перестраиваться, т.к. при вставке записей мы всегда получаем случайное значение GUID и для сохранения упорядоченного вида, новую запись нужно вставить в середину индекса.

Тоесть Вы хотите сказать, что Table Scan будет быстрее работать на наблице в 50к записей, чем Clustered Index Scan???

И что RID Lookup работает быстрее, чем Key lookup при использовании индексов???

И таблица с Identity колонкой и кластерным индексом по ней и Nonclustered Primary Key будет работать медленней, чем таблица без кластерного идекса???

Михаил, я думаю Алексей имел ввиду то, что если в качестве первичных и внешних ключей используется guid, то некластерный индекс будет оптимальным.

Универсальное решение тяжело найти, с учетом того что система работает и под FB и Oracle. Не всегда большое кол-во индексов способствует повышению производительности, иногда производительность резко падает из-за переизбытка индексов. Если вы используете MS SQL 2008, то в нем есть хороший инструмент под названием "Мониторинг ресурсов". Он Вам покажет что происходит с диком, процессором и какие тяжелые запросы. На комьюнити выкладывались так же запросы по рекомендациям использования индексов (какие лишниеи каких не хватает). Так же не забывайте каждый день (точнее ночь) перестраивать индексы, чистить кэш (SQL-ный) и собирать статистику.

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

Если вы мне покажете хоть один(!) запрос из нескольких таблиц где записей больше 100 и он будет работать быстрее без кластерных индексов (конечно не по гуиду) я успокоюсь :smile:

Михаил, я не в коем случае не хотел Вас уличить в некомпетентности. Просто я сейчас поддерживаю две крупные базы, каждая из которых примерно 60 Гб. Одна на Oracle, вторая на MS SQL 2008R2. Ни на одной нет кластерных индексов, это не заслуга, просто так исторически сложилось. Сервера работаю в штатном режиме и не особо напрягаются (я не имею ввиду те ситуации когда процесятся OLAP кубы :lol:, но это не часто и не долго). Так вот, основные тормоза идут на конечных рабочих местах при открытии разделов и экранных форм, т.к. ОЧЕНЬ много логики и ОЧЕНЬ много полей, что очень сильно замедляет билдинг и рендеринг клиентского приложения в целом.

"Домброва Михаил" написал:Если вы мне покажете хоть один(!) запрос из нескольких таблиц где записей больше 100 и он будет работать быстрее без кластерных индексов (конечно не по гуиду) я успокоюсь

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

Войдите или зарегистрируйтесь, чтобы комментировать