для чего нужны временные таблицы в запросе 1с
Временные таблицы в запросах 1С 8.3
Временная таблица
Временные таблицы можно использовать, чтобы не выбирать данные из какой-то таблицы несколько раз. Один раз выбрали их, поместили во временную таблицу и дальше используем уже временную таблицу.
Создается временная таблица с помощью ключевого слова ПОМЕСТИТЬ:
В данном примере выборка из справочника Бренды будет помещена во временную таблицу ВТБренды, а уже потом данные будут выбраны из временной таблицы.
При создании новой временной таблицы она не сохраняется в базе данных. В файловой базе временные таблицы хранятся в оперативной памяти, в MS SQL Server в специальной служебной базе TempDB.
Также временные таблицы можно использовать для оптимизации работы СУБД. Если вместо временной таблицы использовать вложенный запрос, то оптимизатор не будет знать сколько строк в этой таблице и не сможет оптимизировать план запроса. В случае использования временной таблицы количество строк будет известно, что позволит лучше оптимизировать план запроса.
Но у временных таблиц есть и свои минусы:
Менеджер временных таблиц
Менеджер временных таблиц позволяет управлять временными таблицами. Один менеджер временных таблиц может управлять несколькими временными таблицами, но имена временных таблиц в пределах одного менеджера не должны совпадать.
Создать менеджер временных таблиц можно с помощью конструктора:
Временные таблицы запроса
Решил опубликовать эту маленькую статью для самых начинающих программистов 1С. Особенно для тех, кто часто сталкивается с отладкой запросов, а именно временных таблиц этих запросов. Сложность решений продуктов 1С сейчас заключается в том, что код нас уводит далеко вглубь общих модулей, перебрасывая из одного в другой и формируя в них временные таблицы запроса. Назад мы получаем кучу временных таблиц запроса, которые очень неудобно просматривать в отладчике. Для этого я и предлагаю свое ненавязчивое решение в виде расширения.
Для примера я взял конфигурацию ERP 1C. Допустим мне надо при открытии формы сотрудника и получении его кадровых данных и их анализа что-то изменить. Для этого, мне надо увидеть какие временные таблицы использует запрос, что в этих таблицах. Поехали.
Подключаю расширение, надеюсь, как это делать, не стоит рассказывать.
Для примера я нашел модуль, где формируется запрос с кадровыми данными сотрудника, вот он:
Запускаем программу в пользовательском режиме и попробуем открыть форму сотрудника, должна сработать точка останова в месте, где я указал на скрине выше. Далее я бы хотел посмотреть, какие таблицы содержатся в менеджере временных таблиц, для этого мне надо выполнить несколько стандартных операций
То есть выделить Выражение Запрос.МенеджерВременныхТаблиц, потом открыть окно выражений, в этом окне опять открыть у значения свойство Таблицы и снова нажать вычислить выражение и только тогда мы получим список временных таблиц нашего запроса и т.д.
Так как мы люди ленивые, то я в своем расширении это упростил и теперь достаточно в окне выражений набрать следующее:
КС_МенеджерВременныхТаблиц.ПолучитьСписокТаблиц(Запрос.МенеджерВременныхТаблиц)
Вот как это выглядит:
Я всего лишь вывожу то же самое, но в виде списка, но я еще в представление добавил количество строк в каждой таблице, чтобы понимать, что из этого можно просматривать, а на что не стоит тратить времени, так ка таблиц бывает много. Далее вы можете под себя переделать и выводить что вам угодно и в каком виде угодно.
Вторая часть и самая важная это просмотр данных временных таблиц. Если пользоваться стандартными методами, то из скрина выше с временными таблицами мы должны запомнить индекс таблицы, данные которой требуется просмотреть, и потом набрать в окне выражений вот такую команду
Запрос.МенеджерВременныхТаблиц.Таблицы[2].ПолучитьДанные().Выгрузить()
Неудобство в том, что надо всегда понимать какой индекс к какой таблице относится.
Для лентяев, в своем расширении достаточно написать эту команду
КС_МенеджерВременныхТаблиц.ПолучитьДанныеТаблицы(Запрос.МенеджерВременныхТаблиц, 2)
Или, чего нет у 1С, вместо индекса таблицы можем передать имя таблицы
КС_МенеджерВременныхТаблиц.ПолучитьДанныеТаблицы(Запрос.МенеджерВременныхТаблиц, «ВТКадровыеДанныеСотрудников»)
Получим то же самое, но зная имя таблицы не надо искать его индекс
Подведем итог. Расширение использует две функции ПолучитьСписокТаблиц и ПолучитьДанныеТаблицы. Функции можно запускать в любом месте и получать данные временных таблиц. Это на треть сокращает время, чем при поиске стандартным методом.
Прилагаю скрин самих функций, надеюсь Вам не составит труда это быстро сделать. Сам общий модуль Серверный
Проверено на платформе 8.3.18.1289.
Всем спасибо, надеюсь, начинающим это поможет!
Для чего нужны временные таблицы в запросе 1с
Войдите как ученик, чтобы получить доступ к материалам школы
Язык запросов 1С 8.3 для начинающих программистов: пакетные запросы и временные таблицы
Автор уроков и преподаватель школы: Владимир Милькин
Пакетные запросы
Пусть у нас есть запрос, выбирающий наименования цветов:
И запрос, выбирающий наименования вкусов:
Если нам потребуется получить результат каждого из этих запросов, то мы сначала вставим в консоль первый запрос, выполним его и сохраним результат, а затем проделаем то же самое со вторым запросом.
Вот бы иметь возможность выполнить оба этих запроса последовательно, но в один присест. Так сказать в одном пакете. У платформы есть такая возможность и она называется пакетный запрос.
Чтобы получить пакетный запрос нужно перечислить входящие в него запросы и отделить их друг от друга точкой с запятой.
Таким образом наш пакетный запрос для двух вышеперечисленных запросов будет таким:
В результате пакетный запрос вернёт нам сразу две таблицы:
Разумеется в пакетный запрос может входить и 3 и 4 и сколько угодно запросов. Главное отделять их друг от друга точкой с запятой.
Временные таблицы
При пакетном исполнении запроса мы можем любой из его промежуточных результатов поместить во временную таблицу, которая создаётся в памяти компьютера на время исполнения запроса. Это делается для того, чтобы мы смогли обратиться к этому результату в ходе исполнения пакетного запроса ниже.
К примеру, давайте поставим себе цель написать пакетный запрос, который первым запросом выбирает все цвета и помещает их во временную таблицу с именем ТАБЛИЦА_ЦВЕТОВ, вторым запросом выбирает все вкусы и помещает их во временную таблицу с именем ТАБЛИЦА_ВКУСОВ, а третьим запросом делает объединение полученных ранее результатов в одну таблицу:
Обратите внимание на то, что последняя часть пакетного запроса делает выборку из временных таблиц так, словно это реальные таблицы в базе данных.
Временные таблицы вместе с пакетными запросами позволяют писать достаточно сложные запросы, разбивая их на маленькие кусочки.
Не пугайтесь, если применение этих приемов для вас пока не совсем очевидно. Просто имейте в виду такую возможность и однажды (уже на практике) она обязательно вам пригодится.
3 главных вопроса про временные таблицы 1С
Особенности и недостатки временных таблиц
Участников наших курсов часто интересует внутренняя логика работы временных таблиц.
Какие критерии индексирования временных таблиц? Где они хранятся? Нужно ли в явном виде их удалять?
Ответы на эти вопросы мы рассмотрим в данной статье.
Также мы приведем случаи, когда не нужно использовать временные таблицы.
Где хранятся временные таблицы?
Временные таблицы — это объекты СУБД, никаких временных таблиц на сервере 1С нет, и не путайте их с таблицами значений.
Под вопросом: «Где хранятся временные таблицы?» – имеется ввиду физическое расположение, т.е. либо жесткий диск, либо оперативная память.
Вероятно, этот вопрос чаще других остается без ответа, либо ответы на него кардинально различаются.
Но все сходятся в том, что временные таблицы создаются и хранятся в базе TempDB.
Действительно, все временные таблицы относятся к базе данных TempDB, но это вовсе не значит, что они обязательно будут записываться на диск.
Правильный ответ на этот вопрос звучит так: все временные таблицы по умолчанию создаются в оперативной памяти, а именно – в буферном кэше.
Конечно, есть исключения. Например, если таблица слишком большая, то сервер может принять решение сбросить ее на диск. Также возможна ситуация, когда сервер по каким-либо причинам решил отдать память под другие данные, тогда таблица тоже будет записана на диск.
Почему таблица создается именно в памяти? Тут все очевидно – дело в производительности, думаю, не стоит объяснять, что чтение из оперативной памяти гораздо быстрее чтения с диска, даже если этот диск SSD.
Проведем эксперимент и проверим, где создается временная таблица.
Пишем следующий запрос в консоли:
Запускаем трассировку SQL Profiler с событием SQL:BatchComplited, выполняем запрос в консоли и получаем следующий текст SQL запроса:
Здесь мы видим только заполнение временной таблицы, т.к. код создания временных таблиц в нашей трассировке не отображается.
Чтобы понять, где создается временная таблица, необходимо понять, откуда читаются данные – с диска или из памяти. Для этого используем показатель physical reads (количество физических чтений), т.е. сколько 8Кб страниц данных было прочитано с диска для выполнения запроса.
Чтобы получить значение этого показателя, необходимо выполнить создание и чтение временной таблицы в Management Studio.
Создаем новый запрос и пишем следующее:
После выполнения данного кода на закладке «Сообщения» получим следующий текст:
Самое важное здесь то, что данные с диска не читались, т.к. число физических чтений равно 0, при этом есть 1 логическое чтение, т.е. данные были прочитаны только из памяти.
Отсюда можно сделать вывод, что временные таблицы в большинстве случаев создаются и хранятся в оперативной памяти, исключения уже описаны выше.
Надо ли индексировать временные таблицы?
На дисках ИТС, на экзамене 1С: Эксперт, да и я на своих курсах говорю, что нужно индексировать поля условий и соединений во временных таблицах.
Эта рекомендация настолько очевидна, что уже практически никто не подвергает ее сомнению.
Но как показывает практика, чаще всего индексы во временных таблицах не используются, либо используются, но запрос выполняется еще медленнее, чем без них. Скажу даже больше: для себя я сделал вывод, что польза от индексов на временных таблицах – скорее исключение, чем правило.
Это не значит, что индексы не нужно использовать, это значит, что необходимо анализировать каждый конкретный случай, и случаев, когда индекс не нужен, значительно больше.
Именно поэтому на курсах по оптимизации постоянно делается акцент на то, что с каждой проблемой надо разбираться отдельно, а не слепо выполнять рекомендации, не понимая, почему эти рекомендации именно такие.
Давайте рассмотрим ситуацию с индексацией на примере.
Создадим временную таблицу с одним числовым полем и значениями от 1 до 1 млн.
Это можно сделать с помощью следующего пакетного запроса:
Весь запрос выполняется в среднем за 1.2 секунды.
Если посмотреть трассировку SQL Profiler, то мы увидим следующее:
На создание таблицы уходит 1.1 секунда и еще 0.1 секунда на сканирование всей таблицы, чтобы вернуть нам 1 строку.
Давайте посмотрим, что изменится, если добавить индекс в таблицу ВТ_Числа.
На моем компьютере запрос стал выполняться в среднем за 6 секунд.
Время создания таблицы увеличилось с 1 секунды до 5.3, при этом даже поиск по индексу в таблице все равно происходит медленнее, чем сканирование: 0.5 сек. против 0.1 без индекса. Единственное, в чем этот запрос выигрывает, — немного меньше логических чтений: 2057 против 2233 при сканировании.
Используйте индексирование только в том случае, если вы видите от этого явный положительный эффект.
Надо ли явно удалять временные таблицы после создания?
Ответ будет зависеть от способа создания временной таблицы.
Если Вы используете временную таблицу только в одном пакетном запросе, то ваша таблица «живет», пока выполняется этот пакетный запрос. Это значит, что менеджер временных таблиц был создан неявно.
В данном случае MS SQL создает локальную временную таблицу с одной решеткой (#), например #tt1.
Как только пакетный запрос завершается, неявный МВТ закрывается, и автоматически последует команда «Truncate table», которая удаляет созданную таблицу.
Если временная таблица проиндексирована, то сначала будет удален индекс и только потом таблица.
Пример можно посмотреть выше в трассировке.
В данном случае нет необходимости использовать команду «УНИЧТОЖИТЬ», только если Вы не хотите создать в том же запросе новую таблицу с таким же именем, ну или считаете это хорошим стилем написания кода.
Здесь главное понимать, что таблица все равно будет удалена при завершении пакетного запроса.
Ситуация меняется, если Вы явно используете менеджер временных таблиц (МВТ), т.е. создаете соответствующий объект метаданных. В этом случае MS SQL создает глобальную временную таблицу с двумя решетками (##).
Такая таблица будет удалена в любом из следующих вариантов:
Если Вы используете объект МВТ, то временные таблицы рекомендуется удалять одним из первых 2 методов, как только в них отпала необходимость, иначе они будут висеть в памяти сервера СУБД, пока процедура/функция не закончит работу, что не есть хорошо. Если же у Вас процедура, в которой был создан МВТ завершается как раз выполнением запроса, тогда, конечно, МВТ можно не удалять, т.к. сработает 3 условие.
Подведем итог: если Вы не используете МВТ, то явно удалять временную таблицу не требуется, она будет удалена после завершения пакетного запроса.
Если явное объявление МВТ используется, то рекомендуется удалить таблицу вручную, например, в запросе командой «Уничтожить», либо методом МВТ.Закрыть().
Минусы временных таблиц
Идеальных инструментов не бывает, тем более в мире 1С.
Давайте рассмотрим, какие проблемы может принести активное использование временных таблиц.
Чрезмерное разрастание базы TempDB
Если Вы активно используете временные таблицы, то у Вас может довольно сильно разрастаться база TempDB и в один прекрасный день может занять все свободное место на диске. Размер TempDB автоматически только увеличивается, но не уменьшается. Внутри файла место может как заниматься, так и освобождаться, но сам размер файла только увеличивается.
Типичная ситуация, установили обновление, и через несколько дней TempDB раздуло до неимоверных размеров, а потом выясняется, что разработчики переписали запросы с использованием временных таблиц, причем таблицы эти внушительного размера и их много.
Для исправления ситуации необходимо выполнить следующие команды:
Чрезмерное упрощение запросов
Нельзя сказать, что это очень большой минус, но все же.
Часто временные таблицы используются как раз для упрощения сложных запросов, чтобы серверу было легче подобрать оптимальный план, и это правильно.
Но можно встретить и другую крайность: запрос, который вполне можно было бы написать без временных таблиц, и он бы работал быстро и оптимально, все равно пишут через временные таблицы. Просто разработчику лень думать, как это можно сделать по-другому.
Если можно написать оптимальный запрос без использования временных таблиц, то лучше обойтись без них.
Запрос с оптимальным кодом без временных таблиц в любом случае будет работать быстрее и использовать меньше ресурсов, чем запрос с временными таблицами.
Заключение
После прочтения статьи у Вас может сложиться мнение, что я не советую использовать временные таблицы, но это не так. Напротив, я активно их использую для оптимизации запросов, но делаю это только после того, как удостоверюсь в их эффективности в данном конкретном случае.
Временные таблицы — это инструмент для решения определенных задач, а не волшебная таблетка на все случаи жизни.
Бурмистров Андрей
PDF-версия статьи для участников группы ВКонтакте
Если Вы еще не вступили в группу – сделайте это сейчас и в блоке ниже (на этой странице) появятся ссылка на скачивание материалов.
Статья в PDF-формате
Вы можете скачать эту статью в формате PDF по следующей ссылке: Ссылка доступна для зарегистрированных пользователей)
Ссылка доступна для зарегистрированных пользователей)
Ссылка доступна для зарегистрированных пользователей)
Ссылка доступна для зарегистрированных пользователей)
Комментарии / обсуждение (55):
Подскажите, пожалуйста, если во время выполнения больших запросов с огромным количеством временных таблиц tempDb вырастает до верхних пределов, но после завершения всех запросов она хоть и большая, но практически пустая – это является проблемой? Могут ли эти пустоты использоваться эффективно далее при работе? или необходимо сжимать базу?
Добрый день!
После уничтожения объекта типа Запрос в коде 1С – платформа закрывает курсор и СУБД самостоятельно зачищает TempDB, если считает нужным. Но так-же если запрос создает несколько временных таблиц содержащих значительное количество строк, причём для финальной выборки они уже не нужны – можно их явным образом удалить, даже конструктор запроса знает про это. А вот принудительной очистки TempDB не требует (кроме возможно каких-то аварийных ситуаций).
Добрый день. Подскажите, пожалуйста, как будет правильно:
Нужно сделать запросом выборку, которая будет использоваться несколько раз. Например, она будет служить левой таблицей для других таблиц. Я могу 1) Сформировать ВТ с этой выгрузкой и через МенеджерВТ подгружать ее в запросы. Нужно будет каждый раз создавать описание ВТ, и в какой-то момент я могу попутать тип данных в колонке (кстати, нужно ли всегда указывать этот тип)? 2) выгрузить эту выгрузку в таблицу, которую объявлю в разделе переменных и использовать по мере надобности, буду подгружать ее в запросы как параметр? Спасибо
Добрый день!
Не совсем понятно что Вы имеете в виду. Достаточно создать запрос с МенеджеромВременныхТаблиц, например так:
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
И пока этот менеджер будет существовать – все созданные в запросе временные таблицы будут доступны.
Описание… Никаким описанием обычно не пользуюсь, мне достаточно иногда комментариев и всё. Придерживайтесь одних и те-же правил именования – вам самому будет в дальнейшем легче. Если ошибаетесь часто – тщательнее проверяйте код.
По поводу переменных: если это будет переменная модуля – как только управление вернётся в клиентский контекст – переменная будет уничтожена (при следующем обращении к серверу создана заново но ее значение будет Неопределено), использовать реквизит объекта или реквизит формы в качестве экземпляра Менеджера временных таблиц вам не позволит платформа. Поэтому предпочтительнее за 1 вызов получить все требуемые данные с сервера сразу. Выше описано поведение актуальной платформы без режима совместимости в режиме управляемого приложения.
Если на какой-то вопрос не ответил – пожалуйста уточните.
Здравствуйте.
Подскажите, в чем может быть причина. При работе с отладчиком в какой-то момент появилась ошибка:
Временная таблица уже существует “ИмяВТ”. При этом запрос не изменялся.
Опишите ситуацию поподробнее, пока не очень понятно как это воспроизводится. Что именно вы делаете?
Здравствуйте.
А могли бы вы привести пример, когда индексирование действительно нужно?
Скажем так индексирование временных таблиц это точно не “серебряная пуля” и использовать его имеет смысл только если одновременно:
1.временная таблица большая или очень большая.
2.время выполнения запроса неудовлетворительно велико и есть необходимость его сократить.
Это необходимые условия, но не достаточные (достаточных пока никому не удалось сформулировать) т.е. в любом случае следует делать замеры на выполнение запроса/запросов с использованием индекса и без него.
Если эта временная таблица используется несколько раз (в одном запросе или в нескольких (через МенеджерВременныхТаблиц)) по одинаковому условию соединения шансы на выигрыш по скорости серьёзно возрастают.
Здравствуйте!
У Вас на картинке с подписью “Посмотрим, что изменится, если добавить индекс в таблицу ВТ_Числа” иллюстрация к git-flow
Доброго дня, Евгений!
Спасибо, исправили.
при анализе ТЖ заметил что строка МенеджерВременныхТаблиц.Закрыть() выполняется 692738, т.е. 692 секунды.
сами запросы еще не раскопал, но в любом случае странно что удаление таблиц через Truncate может занимать столько времени
или при закрытии еще на что-то может уходить время?
и дополнительно хотел уточнить
в ТЖ как я понимаю идет учет в десятитысячных долях секунды
для данного примера это выглядит так 11:44.2406-6927375
аналогичным образом я настраивал и лог ТЖ
gt property=”duration” value=”100000″
а вот тут “http://www.gilev.ru/privacystatement/” у вас написано что duration учитывается в секундах
“query:ge property=»Duration» value=»10000″ — ограничивает минимальную длительность 10 секундами”
1. В ТЖ для 8.2 время указывается в десятитысячных долях секунды, а в ТЖ для 8.3 в миллионных долях секунды. Если у вас 8.3, то удаление идет 6,9 сек.
2. Удаление ВТ может работать долго если ВТ очень большая (миллионы записей) или если диски сильно загружены (надо смотреть логи PerfMon).
3. Видимо ошибка в статье, 10000 это будет 1 секунда, а не 10.
ну там явно не миллионы записей, ну может пара сотен тысяч
диски флэшовые, очень хорошие
мне вот кажется что в замер попадает не только усечение временных таблиц, а вообще выполнение всех запросов объекта “Запрос” :))
потому что время примерно совпадает с длительностью всего этапа получения данных с сервера (по данным внутренней статистики, скажем так, ключевых операций)
в общем готовлю базу для замеров
в итоге замер показал проблемы совсем в другом месте
Хорошо что получилось разобраться самостоятельно.
Надо просто сравнить замеры 1С с замерами в профайлере, тогда все станет понятно.
удивила странность в ТЖ
Андрей, добрый день! Спасибо большое за статью, очень полезно и информативно. У меня вопрос, произвели переход на 8.3.,теперь при попытке открыть проводки документа (Дт/Кт) регистра бухгалтерии возникает ошибка “Попытка вставки неуникального значения в уникальный индекс: Microsoft SQL Server Native Client 10/0: Не удается вставить повторяющуюся строку ключа в объект «dbo.#tt35» с уникальным индексом «idx35»”. Я так понимаю что проблема со временной таблицей. Но вот вопрос, что делать дальше. Как можно исправить ситуацию? Можете дать рекомендацию.
Сходу, без анализа ситуации могу предложить попробовать следующие варианты:
– Поставить режим совместимости с 8.2
– Сделать ТиИ
– Сделать выгрузку в DT файл и загрузку из него
Если это не поможет тогда уже надо будет шаманить на месте
Добрый день, Андрей! Очень полезная информация. Глобальный вопрос в том, что лучше для манипуляций с данными использовать Менеджер временных таблиц и через язык запросов проводить модификацию таблицы или лучше все же выгружать в ТЗ и старым добрым способом работать операторами найти и менять значения в Таблице, удалять и добавлять строки и колонки=)?
В качестве конкретного вопроса. Что более быстрее и оптимальнее будет отрабатываться:
1. Оператор “Найти” по таблице значений
2. Отбор по виртуальной таблице через оператор “Где” Набор данных порядка 1 млн. строк
Правильный ответ: провести опыт и посмотреть на вашем сервере и ваших данных.
подскажите пожалуйста как в 83 можно кэшировать мвт между серверными вызовами? в 82 можно было его положить в хранилище значений, а отныне больше нет…
Добрый день! Подскажите, если я помещаю во временную таблицу данные, которые изначально индексированы, то эти поля во временной уже не индексированы?
Допустим, запрос:
выбрать Т.Ссылка, Т.Контрагент, Т.Подразделение
Поместить ВТ
ИЗ Документ.ПоступлениеТоваровУслуг КАК Т;
Ссылка ведь всегда индексирована, и если дальше в запросе мы по этой ссылке будем соединять эту таблицу с другой по ссылке, то имеет смысл заново индексировать поле Ссылка (при большом количестве записей)? (про чтение данных из документов, а не из регистров сейчас речи не идет).
> если я помещаю во временную таблицу данные, которые изначально индексированы, то эти поля во временной уже не индексированы?
Да, во временной таблице индекса по этим полям уже не будет.
> имеет смысл заново индексировать поле Ссылка (при большом количестве записей)?
Это зависит от вашего запроса и ваших данных. Попробуйте сделайте индекс на временной таблице и замерьте время выполнения. Зачастую индекс на временных таблицах не используется, либо используется но на его создание тратится больше времени чем на сканирование всей таблицы. Проведите опыт и посмотрите поможет ли индекс на временной таблице именно в вашем случае.
Андрей, спасибо за ваш труд. Курс по оптимизации мне очень понравился, хорошо структурирован, все по делу и без воды. За статьи и обратную связь отдельное спасибо!
Спасибо, за добрые слова, по таким комментарием понимаешь что все делалось не зря.
Следующая версия курса должна быть еще лучше 🙂
Кажется у вас опечатка или ошибка… ))
>Как только пакетный запрос завершается, неявный МВТ закрывается, и >автоматически последует команда «Truncate table», которая удаляет >созданную таблицу.
Скорее всего имелось в виду Drop table.
Truncate table – Удаляет все строки в таблице, не записывая в журнал удаление отдельных строк.
А я думал заметит ли кто – нибудь 🙂
Да, 1С всегда используется Truncate вместо Drop, что бы по возможности не создавать новую таблицу со такой же структурой, а использовать уже существующую, но принципиально сути это не меняет.
не в тему – прочитал и опять нахлынуло, имхо, как хотелось бы, чтобы действительно толковые головы разработчиков платформы 1С приложили усилия к продвижению по пути (в целом очень сложному пути) к избавлению от этих временных таблиц при написании запросов вместо создания сомнительной полезности управляемых форм и тем более Такси
Уже пора рубрику открывать “Осторожно! Гилев!” или “Киноляпы Гилева” (это про видеоуроки).
Похоже к нам заглянули старожилы Мисты ))
Ok, но здесь не получится развести традиционный флуд 😉
Вообще без конкретики с Вашей стороны сложно на это что-то ответить.
И непонятно, как этот комментарий вообще относится к временным таблицам.
Не понял. Вы серьезно говорите, что если используется явно МВТ, то создаются глобальные таблицы. Но глобальные таблицы существуют до тех пор пока не завершаться все сеансы (ВСЕ, а не только тот spid, который ее создал). То есть выход из процедура или функции (неявное закрытие МВТ), я уже молчу о сбоях, не приведут к уничтожению глобальной таблицы.
2) Если таблица глобальная, то она будет доступна всем сеансам, то есть если 2 пользователя выполняют одинаковую процедуру, то они будут мешать друг другу, то есть они не смогут параллельно их создавать, то есть возникнет проблема изоляции.
ЗЫ: Вообще не понимаю зачем обсуждать индексы временной таблицы, они ничем не отличаются от индексов обычных таблиц, кроме как что средствами 1С нельзя создать более одного индекса.
1) глобальные таблицы существуют до тех пор пока не завершаться все сеансы (ВСЕ, а не только тот spid, который ее создал)
—
Вы не правы, в контексте 1С глобальная таблица уничтожается в любом из трех перечисленных в статье случаев. Можете самостоятельно проверить в Profiler. При штатном завершении программы, никаких сбоев при работы временных таблиц не будет.
2) Если таблица глобальная, то она будет доступна всем сеансам, то есть если 2 пользователя выполняют одинаковую процедуру, то они будут мешать друг другу, то есть они не смогут параллельно их создавать, то есть возникнет проблема изоляции.
—
Вы снова ошибаетесь.
СУБД присваивает уникальные служебные имена временным таблицам, выглядят они примерно так «##tt1_____________________________________________000000000087».
Таким образом 1С сеанс никак не сможет прочитать данные временной таблицы другого сеанса. Более того, если бы то о чем вы говорите было бы возможно, то 1С вообще бы не смогла нормально работать в многопользовательском режиме.
3) Вообще не понимаю зачем обсуждать индексы временной таблицы, они ничем не отличаются от индексов обычных таблиц, кроме как что средствами 1С нельзя создать более одного индекса.
—
Да, я заметил что вы не понимаете.
Смысл статьи в том, что индексы на временной таблице нужно создавать не всегда и везде, а только там, где от этого есть реальная польза, т.е. где затраты на создание индекса перекрывается выигрышем в скорости чтения. Сейчас же многие разработчики слепо следуют рекомендации, не отслеживая при этом используется ли вообще созданный ими индекс, а если да, то приносит ли он желаемый эффект.
“Сейчас же многие разработчики слепо следуют рекомендации, не отслеживая при этом используется ли вообще созданный ими индекс, а если да, то приносит ли он желаемый эффект.”
Сорри за некропостинг, но я прямо себя вспомнил некоторое время назад, когда сдал спеца по платформе и гордо везде совал индексы. И очень увидился, увидев, что запрос БЕЗ индексов (в моем случае) стал работал в два раза быстрее 🙂
Да, к сожалению такое бывает чаще чем хотелось бы.
Провел эксперимент с индексированием временной таблицы на SQL Server 2012. Как и ожидалось, с индексом выборка работает существенно быстрее, чем без: примерно 1 миллисекунда против 80. По статистике чтений все также в пользу индекса. Не совсем понятно, почему у вас получился такой результат.
Вот поэтому я и говорю что нужно смотреть в каждом конкретном случае.
Поставил SQL Server 2014, платформа 8.3, результат такой же как в статье, запрос без индекса все равно работает быстрее чем с индексом.
ещё бы, именно MS SQL 2014 представлялся публике, как отличный инструмент “инмемори”-оптимизации. На других серверах и версиях верно “нужно смотреть в каждом конкретном случае”.
Дело здесь не в In-Memory OLTP, временная таблица и так была в памяти. Просто именно на моем компьютере данный запрос работает быстрее со сканированием, на другом компьютере с другой версией СУБД возможна другая ситуация.
Быстрее работает выборка (ВЫБРАТЬ ВТ_Числа.Число ИЗ ВТ_Числа КАК ВТ_Числа ГДЕ ВТ_Числа.Число = 777) или вставка + выборка?
На 2014 и 8.3 быстрее именно вставка в таблицу без индекса, сама выборка без индекса медленнее, но в итоге затраты на создание индекса так велики, что для данного запроса получается выгоднее его не создавать.
это ок, меня смутило что у вас select с индексом медленнее отработал.
В момент написания статьи использовалась платформа 8.2 и SQL Server 2008 R2, там селект действительно работал медленнее.
Хорошая статья, но по пункту “Надо ли индексировать временные таблицы?” – типовая рекомендация правильная, и лучше указывать вместо “Используйте индексирование только в том случае, если вы видите от этого явный положительный эффект.” формулировку “Используйте нужно индексировать поля условий и соединений во временных таблицах во всех случаях, кроме тех где нет явного положительного эффекта.”
Кроме того Вы привели частный пример, где создается одна таблица и производится выборка по одному полю, но если бы Вы привели пример запроса, где данные из первой таблицы выбираются не единожды, то результат был бы совершенно другой (вспомните хотя бы многоэтажные запросы ЗУПа).
Также не указан пример при соединении двух таблиц значительного объема.
Для себя я сделал вывод, что:
– индексирование по полям поиска не следует делать, если поиск по таблице выполняется 1-3 раза, тогда table scan без создания индекса сработает быстрее
– индексирование по условиям соединения не следует делать, если соединяемая таблица содержит НЕ БОЛЕЕ трех записей, тогда nested loop также отработает быстрее.
>по пункту «Надо ли индексировать временные таблицы?» — типовая рекомендация правильная, и лучше указывать вместо «Используйте индексирование только в том случае, если вы видите от этого явный положительный эффект.» формулировку «нужно индексировать поля условий и соединений во временных таблицах во всех случаях, кроме тех где нет явного положительного эффекта.»
Типовая рекомендация говорит, что поля условий и соединений нужно индексировать ВСЕГДА и никаких если.
>«нужно индексировать поля условий и соединений во временных таблицах во всех случаях, кроме тех где нет явного положительного эффекта.»
Вы предлагаете делать лишнюю операцию и лишний раз занимать ресурсы сервера. Допустим что разницы во времени не заметно т.к. железо сглаживает углы, и индекс на таблице не используется, так зачем же делать лишнюю операцию? Тем более что со временем нагрузка может увеличится и тогда разница в выполнении может быть заметна.
>Кроме того Вы привели частный пример, где создается одна таблица и производится выборка по одному полю, но если бы Вы привели пример запроса, где данные из первой таблицы выбираются не единожды, то результат был бы совершенно другой (вспомните хотя бы многоэтажные запросы ЗУПа).
Также не указан пример при соединении двух таблиц значительного объема.
Именно поэтому я и говорю что не нужно отказываться от индексов на временных таблицах, их нужно использовать, но только если есть явный эффект.
>индексирование по полям поиска не следует делать, если поиск по таблице выполняется 1-3 раза, тогда table scan без создания индекса сработает быстрее
Всегда зависит от конкретной ситуации
>индексирование по условиям соединения не следует делать, если соединяемая таблица содержит НЕ БОЛЕЕ трех записей, тогда nested loop также отработает быстрее.
Если в таблице 3 строки, нет абсолютно никакого смысла ее индексировать, ни поля соединений ни условий. Nested Loops с поиском по индексу никак не связан, при возможности Nested Loops может использовать индекс для поиска.













