Выявление таблиц БД, занимающих много места.
Для начала я решил выяснить, какие данные занимают много места. Хотел решить этот вопрос по-простому - скачать обработку с Infostart. По-простому получилось как-то не очень просто, оказалось, надо еще с обработкой разбираться. При помощи MS SQL, на мой взгляд, намного проще.
1. Выполняем запрос на MS SQL
USE [DatabaseName]
GO
CREATE TABLE #temp (
table_name sysname ,
row_count INT,
reserved_size VARCHAR(50),
data_size VARCHAR(50),
index_size VARCHAR(50),
unused_size VARCHAR(50))
SET NOCOUNT ON
INSERT #temp
EXEC sp_msforeachtable 'sp_spaceused ''?'''
SELECT a.table_name,
a.row_count,
COUNT(*) AS col_count,
a.data_size,
a.index_size
FROM #temp a
INNER JOIN information_schema.columns b
ON a.table_name collate database_default
= b.table_name collate database_default
GROUP BY a.table_name, a.row_count, a.data_size, a.index_size
ORDER BY CAST(REPLACE(a.data_size, ' KB', '') AS integer) DESC
DROP TABLE #temp
Вместо [DatabaseName] нужно подставить название нужной базы.
2. Результат запроса прекрасно копируется в MS Excel. С помощью функции " ПОДСТАВИТЬ " избавляемся от " KB", и преобразуем значения из строк в числа.
3. Вычисляем процент от занимаемого места.
4. По названию таблиц определям метаданные.
тзСтруктураХранения = ПолучитьСтруктуруХраненияБазыДанных(,);
СтруктураОтбора = Новый Структура("ИмяТаблицыХранения", НазваниеТаблицы);
мстзСтруктураХранения = тзСтруктураХранения.НайтиСтроки(СтруктураОтбора);
тзРезультат = тзСтруктураХранения.Скопировать(мстзСтруктураХранения);
Для Каждого стзРезультат Из тзРезультат Цикл
Сообщить("" + стзРезультат.Метаданные + " " + стзРезультат.Назначение);
КонецЦикла;
В моем случае, получился результат, приведенный в таблице:
Учет НДС (книги покупок/ продаж) в данной базе не ведется. Расчет с контрагентами (не путать со взаиморасчетами) также не ведется. Результат мы видим в таблице - регистры превратились в свалку.
Очистка записей регистров накопления
План работ:
- Внести изменения в алгоритмы, делающие записи по регистрам, которые нужно очистить.
- Очистка регистров.
- Тестирование.
Изменение алгоритмов
Сначала я попробовал воспользоваться глобальным поиском в модулях по названию регистра. В результате получил большое количество совпадений.
Остановился на следующем методе.
- Выписал все возможные регистраторы (документы);
- В каждом документе анализировал проведение документа.
Такой метод оказался намного проще, естественно, не даёт гарантированный 100% результат.
Очистка регистров
Для очистки регистров написал следующую обработку:
Процедура ОчиститРегистр(НаименованиеРегистра)
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| " + НаименованиеРегистра + ".Регистратор,
| " + НаименованиеРегистра + ".Период КАК Период
|ИЗ
| РегистрНакопления." + НаименованиеРегистра + " КАК " + НаименованиеРегистра + "
|
|УПОРЯДОЧИТЬ ПО
| Период УБЫВ";
Выборка = Запрос.Выполнить().Выбрать();
Индикатор = 0;
ЭлементыФормы.Индикатор.МаксимальноеЗначение = Выборка.Количество();
Пока Выборка.Следующий() Цикл
нзРегистр = РегистрыНакопления[НаименованиеРегистра].СоздатьНаборЗаписей();
нзРегистр.Отбор.Регистратор.Значение = Выборка.Регистратор;
нзРегистр.Записать();
Индикатор = Индикатор + 1;
КонецЦикла;
РегистрыНакопления[НаименованиеРегистра].ПересчитатьИтоги();
КонецПроцедуры
Процедура КнопкаВыполнитьНажатие(Кнопка)
// Вставить содержимое обработчика.
СписокРегистров = Новый Массив();
СписокРегистров.Добавить("НДСРасчетыСПокупателями");
СписокРегистров.Добавить("НДСРасчетыСПоставщиками");
СписокРегистров.Добавить("РасчетыСКонтрагентами");
СписокРегистров.Добавить("НДСПредъявленный");
ЭлементыФормы.Индикатор1.МаксимальноеЗначение = 4;
Индикатор1 = 0;
Для Каждого НаименованиеРегистра Из СписокРегистров Цикл
Индикатор1 = Индикатор1 + 1;
ОчиститРегистр(НаименованиеРегистра);
КонецЦикла;
КонецПроцедуры
Начальный вариант кода был без пересчета остатков по регистрам, я думал, что при удалении записей автоматически произойдет пересчет итогов, я ошибался.
О том, что при удалении записей из таблицы файл не уменьшается, я знал давно. Но раньше я это больше ассоциировал со справочниками, и почему-то не связывал с регистрами. А ведь именно в случае с регистрами очень часто записи удаляются. Восстанавление последовательности - регулярная операция. Следовательно, после восстановления последовательности документов нужно упаковывать таблицы регистров.
Тестирование
Тестирование я проводил следующим образом.
- Перепроводил документы (за месяц);
- Проверка на наличие записей в регистрах;
- Проверка изменения остатков.
При правке кода для удаления проведения по регистру "Расчеты с покупателями", была возможность повредить код проведения по регситру "Заявки на расходование средств". Поэтому я решил проконтролировать остатки по данному регистру следующим образом:
- Остатки по регистру выгрузил в файл.
- Перепровел документы.
- Сравнил остатки в файле с остатками в базе.
Код обработки:
Перем ТипДиалога;
Процедура ВыбФайлНачалоВыбора(Элемент, СтандартнаяОбработка)
// Вставить содержимое обработчика.
длгВыборФайла = Новый ДиалогВыбораФайла(ТипДиалога);
Если длгВыборФайла.Выбрать() Тогда
ВыбФайл = длгВыборФайла.ПолноеИмяФайла;
КонецЕсли;
КонецПроцедуры
Процедура СохранитьНажатие(Элемент)
// Вставить содержимое обработчика.
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ
| ЗаявкиНаРасходованиеСредствОстатки.ДоговорКонтрагента,
| ЗаявкиНаРасходованиеСредствОстатки.Сделка,
| ЗаявкиНаРасходованиеСредствОстатки.ЗаявкаНаРасходование,
| ЗаявкиНаРасходованиеСредствОстатки.СтатьяДвиженияДенежныхСредств,
| ЗаявкиНаРасходованиеСредствОстатки.Проект,
| ЗаявкиНаРасходованиеСредствОстатки.СуммаВзаиморасчетовОстаток,
| ЗаявкиНаРасходованиеСредствОстатки.СуммаУпрОстаток,
| ЗаявкиНаРасходованиеСредствОстатки.СуммаОстаток
|ИЗ
| РегистрНакопления.ЗаявкиНаРасходованиеСредств.Остатки КАК ЗаявкиНаРасходованиеСредствОстатки";
тзОстатки = Запрос.Выполнить().Выгрузить();
ЗначениеВФайл(ВыбФайл, тзОстатки);
КонецПроцедуры
Процедура СравнитьНажатие(Элемент)
// Вставить содержимое обработчика.
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ
| ЗаявкиНаРасходованиеСредствОстатки.ДоговорКонтрагента,
| ЗаявкиНаРасходованиеСредствОстатки.Сделка,
| ЗаявкиНаРасходованиеСредствОстатки.ЗаявкаНаРасходование,
| ЗаявкиНаРасходованиеСредствОстатки.СтатьяДвиженияДенежныхСредств,
| ЗаявкиНаРасходованиеСредствОстатки.Проект,
| -ЗаявкиНаРасходованиеСредствОстатки.СуммаВзаиморасчетовОстаток КАК СуммаВзаиморасчетовОстаток,
| -ЗаявкиНаРасходованиеСредствОстатки.СуммаУпрОстаток КАК СуммаУпрОстаток,
| -ЗаявкиНаРасходованиеСредствОстатки.СуммаОстаток КАК СуммаОстаток
|ИЗ
| РегистрНакопления.ЗаявкиНаРасходованиеСредств.Остатки КАК ЗаявкиНаРасходованиеСредствОстатки";
тзРезультат = Запрос.Выполнить().Выгрузить();
тзОстатки = ЗначениеИзФайла(ВыбФайл);
Для Каждого стзОстатки Из тзОстатки Цикл
стзРезультат = тзРезультат.Добавить();
ЗаполнитьЗначенияСвойств(стзРезультат, стзОстатки);
КонецЦикла;
тзРезультат.Свернуть("ДоговорКонтрагента,Сделка,ЗаявкаНаРасходование,СтатьяДвиженияДенежныхСредств,Проект", "СуммаВзаиморасчетовОстаток,СуммаУпрОстаток,СуммаОстаток");
Сч = тзРезультат.Количество();
Пока Сч > 0 Цикл
Сч = Сч - 1;
стзРезультат = тзРезультат[Сч];
Если стзРезультат.СуммаВзаиморасчетовОстаток = 0
И стзРезультат.СуммаУпрОстаток = 0
И стзРезультат.СуммаОстаток = 0 Тогда
тзРезультат.Удалить(стзРезультат);
КонецЕсли;
КонецЦикла;
тзРезультат.ВыбратьСтроку();
КонецПроцедуры
ТипДиалога = РежимДиалогаВыбораФайла.Открытие;
Заключение
Скорее всего, материал я изложил совсем не лаконично, а скорее наборот, но с чего-то надо начинать. Главное, чтобы информация была полезной, а статью потом можно будет и переписать.