Как узнать размеры таблиц для баз данных 1C-SQL   

Как известно, для базы данных в формате DBF легко можно посмотреть размер данных и размер индексов для каждой таблицы. Для баз данных в формате SQL такой легкой возможности нет. На самом деле, конечно же, такая возможность есть, просто до нее тяжелей добраться. SQL-сервер хранит сведения обо всех параметрах таблиц в своих системных таблицах, поэтому, чтобы получить информацию о таблицах приходится либо воспользоваться хранимой процедурой sp_spaceused, которая предоставляет всю необходимую информацию, либо писать свой код. Недостаток этой процедуры в том, что она выдает характеристику только одной таблицы за один раз. Таким образом, средства, сравнимого по легкости с просмотром каталога базы данных формата DBF, для SQL-варианта базы нет.

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

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

Для работы необходимо наличие библиотеки rainbow.dll в папке ИБ, которую можно взять здесь. За основу был взят текст хранимой процедуры sp_spaceused, который был подправлен так, чтобы быть полностью совместимым с Rainbow.

Текст обработки представлен ниже:

Перем СЗ;
//________________________________________________________
Процедура ПодготовитьСЗ()
    глМета=СоздатьОбъект("MetaDataWork");
    СЗ=СоздатьОбъект("СписокЗначений");
    СЗ.Установить("_1SACCS","План счетов");
    СЗ.Установить("_1SACCSEL","Отбор проводок по счетам");
    СЗ.Установить("_1SBKTTL","Остатки (сальдо и обороты по субконто)");
    СЗ.Установить("_1SBKTTLC","Итоги (сальдо и обороты по синтетическим счетам)");
    СЗ.Установить("_1SCONST","Периодические константы");
    СЗ.Установить("_1SCORENT","Корректные проводки");
    СЗ.Установить("_1SCRDOC","Графы отбора и ссылки документов");
    СЗ.Установить("_1SDBSET","Базы данных (УРБД)");
    СЗ.Установить("_1SDNLOCK","Блокировка номеров документов");
    СЗ.Установить("_1SDWNLDS","Пакеты обмена данными (УРБД)");
    СЗ.Установить("_1SENTRY","Проводки");
    СЗ.Установить("_1SJOURN","Журналы документов");
    СЗ.Установить("_1SOPER","Операции");
    СЗ.Установить("_1SSBSEL","Отбор проводок по субконто");
    СЗ.Установить("_1SSTREAM","Последовательности");
    СЗ.Установить("_1SSYSTEM","Системная");
    СЗ.Установить("_1STOPER","Типовые операции");
    СЗ.Установить("_1SUIDCTL","Уникальности");
    СЗ.Установить("_1SUPDTS","Обновления объектов (УРБД)");
    СЗ.Установить("_1SUSERS","Счетчики соединений");
    СЗ.Установить("_1SCONNECT","Соединение");
    СЗ.Установить("CJPROP","Параметры ЖР");
    СЗ.Установить("CL","Календари");
    //Справочники
    Для к=1 по Метаданные.Справочник() Цикл
        ТекИд=Метаданные.Справочник(к).Идентификатор;
        ТекИмяТаблицы=глМета.ИмяТаблицыСправочника(ТекИд);
        ТекНазваниеТаблицы="Справочник."+ТекИд;
        СЗ.Установить(ТекИмяТаблицы,ТекНазваниеТаблицы);
    КонецЦикла;
    //Документы
    Для к=1 по Метаданные.Документ() Цикл
        ТекИд=Метаданные.Документ(к).Идентификатор;
        ТекИмяТаблицы=глМета.ИмяТаблицыШапки(ТекИд);
        ТекНазваниеТаблицы="Документ."+ТекИд+" (шапка)";
        СЗ.Установить(ТекИмяТаблицы,ТекНазваниеТаблицы);
        Если Метаданные.Документ(к).РеквизитТабличнойЧасти()>0 Тогда
            ТекИмяТаблицы=глМета.ИмяТаблицыТабличнойЧасти(ТекИд);
            ТекНазваниеТаблицы="Документ."+ТекИд+" (таблица)";
            СЗ.Установить(ТекИмяТаблицы,ТекНазваниеТаблицы);
        КонецЕсли;
    КонецЦикла;
    //Регистры
    Для к=1 по Метаданные.Регистр() Цикл
        ТекИд=Метаданные.Регистр(к).Идентификатор;
        ТекИмяТаблицы=глМета.ИмяТаблицыИтогов(ТекИд);
        ТекНазваниеТаблицы="Регистр."+ТекИд+" (итоги)";
        СЗ.Установить(ТекИмяТаблицы,ТекНазваниеТаблицы);
        ТекИмяТаблицы=глМета.ИмяТаблицыДвижений(ТекИд);
        ТекНазваниеТаблицы="Регистр."+ТекИд+" (движения)";
        СЗ.Установить(ТекИмяТаблицы,ТекНазваниеТаблицы);
    КонецЦикла;
    //Журналы расчета
    Для к=1 по Метаданные.ЖурналРасчетов() Цикл
        ТекИд=Метаданные.ЖурналРасчетов(к).Идентификатор;
        ТекИмяТаблицы=глМета.ИмяТаблицыЖР(ТекИд);
        ТекНазваниеТаблицы="Журнал расчетов."+ТекИд;
        СЗ.Установить(ТекИмяТаблицы,ТекНазваниеТаблицы);
    КонецЦикла;
КонецПроцедуры
//________________________________________________________
Процедура Сформировать()
    ПодготовитьСЗ();
    ТЗ=СоздатьОбъект("ТаблицаЗначений");
    ТЗ.НоваяКолонка("Имя","Строка");
    ТЗ.НоваяКолонка("Название","Строка");
    ТЗ.НоваяКолонка("Количество","Число");
    ТЗ.НоваяКолонка("Всего","Число");
    ТЗ.НоваяКолонка("Данные","Число");
    ТЗ.НоваяКолонка("Индексы","Число");
    ТЗ.НоваяКолонка("Свободно","Число");
    СписокТаблиц=СоздатьОбъект("СписокЗначений");
    //________________________________________________________
    ЗапросРадуги=СоздатьОбъект("ODBCQuery");
    Если ЗапросРадуги.Prepare("Select RTRIM(CONVERT(char(30),TABLE_NAME)) from INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND TABLE_NAME<>'dtproperties'",0,0)=1 Тогда
        Если ЗапросРадуги.Open()=1 Тогда
            ЗапросРадуги.GotoNext();
            Пока ЗапросРадуги.IsOK()=1 Цикл
                СписокТаблиц.ДобавитьЗначение(ЗапросРадуги.GetString(0));
                ЗапросРадуги.GotoNext();
            КонецЦикла;
            ЗапросРадуги.Close();
        Иначе
            Предупреждение("Ошибка открытия запроса!",10);
        КонецЕсли;
        ЗапросРадуги.Reset();
    Иначе
        Предупреждение("Ошибка выполнения запроса!",10);
    КонецЕсли;
    //Теперь анализируем
    Для к=1 по СписокТаблиц.РазмерСписка() Цикл
        ТекстЗапроса="DECLARE @id int
        |DECLARE @pages int
        |DECLARE @rows int
        |DECLARE @reserved dec(15)
        |DECLARE @data dec(15)
        |DECLARE @indexp dec(15)
        |DECLARE @unused dec(15)
        |SELECT @id = id FROM sysobjects WHERE id = object_id('"+СписокТаблиц.ПолучитьЗначение(к)+"')
        |SELECT @reserved=SUM(reserved) FROM sysindexes WHERE indid in (0, 1, 255) and id = @id
        |SELECT @pages = SUM(dpages) FROM sysindexes WHERE indid < 2 and id = @id
        |SELECT @pages = @pages + isnull(SUM(used), 0) FROM sysindexes WHERE indid = 255 and id = @id
        |SET @data = @pages
        |SET @indexp = (select SUM(used) FROM sysindexes WHERE indid in (0, 1, 255) and id = @id) - @data
        |SET @unused = @reserved - (SELECT SUM(used) FROM sysindexes WHERE indid in (0, 1, 255) and id = @id)
        |SELECT @rows=rows FROM sysindexes WHERE indid < 2 and id = @id
        |SELECT name = RTRIM(CONVERT(char(30),object_name(@id))), rows = RTRIM(CONVERT(char(11), @rows)),
        |reserved = LTRIM(str(@reserved * d.low / 1024.,15,0)),data = LTRIM(str(@data * d.low / 1024.,15,0)),
        |index_size = LTRIM(str(@indexp * d.low / 1024.,15,0)),unused = LTRIM(str(@unused * d.low / 1024.,15,0))
        |FROM master.dbo.spt_values d WHERE d.number = 1 and d.type = 'E'";
        Если ЗапросРадуги.Prepare(ТекстЗапроса,0,0)=1 Тогда
            Если ЗапросРадуги.Open()=1 Тогда
                ЗапросРадуги.GotoNext();
                Пока ЗапросРадуги.IsOK()=1 Цикл
                    ТЗ.НоваяСтрока();
                    ТЗ.Имя=ЗапросРадуги.GetString(0);
                    ТЗ.Название=СЗ.Получить(ТЗ.Имя);
                    ТЗ.Количество=Число(ЗапросРадуги.GetString(1));
                    ТЗ.Всего=Число(ЗапросРадуги.GetString(2));
                    ТЗ.Данные=Число(ЗапросРадуги.GetString(3));
                    ТЗ.Индексы=Число(ЗапросРадуги.GetString(4));
                    ТЗ.Свободно=Число(ЗапросРадуги.GetString(5));
                    ЗапросРадуги.GotoNext();
                КонецЦикла;
                ЗапросРадуги.Close();
            Иначе
                Предупреждение("Ошибка открытия запроса!",10);
                Прервать;
            КонецЕсли;
            ЗапросРадуги.Reset();
        Иначе
            Предупреждение("Ошибка выполнения запроса!",10);
            Прервать;
        КонецЕсли;
    КонецЦикла;
    ЗапросРадуги="";
    //________________________________________________________
    Таб=СоздатьОбъект("Таблица");
    Таб.ИсходнаяТаблица("Таблица");
    Таб.ВывестиСекцию("Заголовок");
    ТЗ.ВыбратьСтроки();
    Пока ТЗ.ПолучитьСтроку()=1 Цикл
        Таб.ВывестиСекцию("Строка");
    КонецЦикла;
    Таб.ВывестиСекцию("Итоги");
    Таб.Опции(0,0,0,0);
    Таб.ТолькоПросмотр(1);
    Таб.Показать();
КонецПроцедуры
//________________________________________________________
Процедура Обновить()
    ЗапросРадуги=СоздатьОбъект("ODBCQuery");
    ТекстЗапроса="DBCC UPDATEUSAGE (0) WITH NO_INFOMSGS";
    Если ЗапросРадуги.Prepare(ТекстЗапроса,0,0)=1 Тогда
        Если ЗапросРадуги.Open()=1 Тогда
        Иначе
            Предупреждение("Ошибка открытия запроса!",10);
        КонецЕсли;
        ЗапросРадуги.Reset();
    Иначе
        Предупреждение("Ошибка выполнения запроса!",10);
    КонецЕсли;
    ЗапросРадуги="";
КонецПроцедуры
//________________________________________________________
Процедура ПриОткрытии()
    ЗагрузитьВнешнююКомпоненту("rainbow.dll");
КонецПроцедуры

Эту обработку можно загрузить в разделе "Скачать".

 


 

Перепечатка, воспроизведение в любой форме, распространение, в том числе в переводе, любых материалов с сайта www.softpoint.ru возможны только с письменного разрешения компании "СофтПоинт". Это правило действует для всех без исключения случаев, кроме тех, когда в материале прямо указано разрешение на копирование (основание: Закон Российской Федерации "Об авторском праве и смежных правах").