1с внутреннее соединение или условие где

Обновлено: 06.07.2024

В чем отличия между сеансом и соединением? Этот, на первый взгляд, простой вопрос на экзамене 1С:Эксперт многих ставит в тупик. Несмотря на немалый опыт программирования, сформулировать четкий и правильный ответ сможет далеко не каждый специалист.

В данной статье проведем детальный разбор этого вопроса. Для начала рассмотрим по отдельности понятия сеанс и соединение в 1С:Предприятие. Отметим, что информация актуальна для версий платформы 8.2.x и 8.3.x.

Сеанс 1С

Обратимся к руководству администратора. В нем понятие сеанса определено следующим образом:

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

Можно сказать, что кластер серверов не видит пользователей, вместо них он видит сеансы и сеансовые данные. В консоли управления кластером в принципе отсутствует раздел «Пользователи», под пользователями кластер понимает сеансы.

Это подтверждает визуальное представление пункта «Сеансы» – иконка отображается в виде пользователей.

Следует уточнить, что под активным пользователем не обязательно понимается клиентское соединение, это также может быть:

Сеансовые данные

Рассмотрим понятие сеансовые данные. Сеанс содержит в себе некоторую информацию, такую как:

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

Такая информация называется сеансовыми данными. Причем для каждого активного пользователя сеансовые данные свои, и актуальны они только на время его работы. Если пользователь покидает базу (завершил сеанс) – его сеансовые данные удаляются.

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

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

Для поддержания сеанса тонкий клиент и веб-клиент обеспечивают обращение к кластеру не реже 1 раза в 10 минут.

Соединение 1С

Теперь разберемся с понятием соединение. Вновь обратимся к руководству администратора:

Соединение является средством доступа сеансов к кластеру серверов «1С:Предприятие», содержит ограниченное множество данных соединения, не отождествляется с активным пользователем.

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

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

Нужно отметить, что сеансовые данные хранятся на сервере, поэтому если разрыв соединения длится менее 20 минут, то на сеансе это не отразится, ведь соединение – всего лишь средство доступа.

Также соединения используются для взаимодействия процессов кластера, то есть рабочие процессы (rphost) общаются с менеджером кластера (процесс rmngr) при помощи соединений, а не с помощью сеансов.

Отличия соединения от сеансов

Для того чтобы описать основное отличие данных понятий, приведем аналогию.

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

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

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

PDF-версия статьи для участников группы ВКонтакте

Станьте экспертом по оптимизации 1С, изучив наш курс
«Ускорение и оптимизация систем на 1С:Предприятие 8.3 (2016). Подготовка на 1С:Эксперт по технологическим вопросам»

35 учебных часов, подготовка к 1С:Эксперт, правильная настройка серверной части, оптимизация кода, мониторинг загруженности оборудования и прочие взрослые вещи.

Комментарии / обсуждение (11):

1. При удалении соединения сеанс остается, ему назначается новое соединение.
2. Как я и описал, это так же средство общения между процессами. Не понятно зачем устанавливать соединения между несколькими источниками. У вас есть только 2 процессы которые в момент времени могут между собой общаться.
3. Наверняка это знают только разработчики платформы, в документации такие тонкости не описаны.

1. Теоретически это так и должно быть. Но практика показывает, что если удалить соединение, тогда сеанс тоже удаляется, при этом нового соединения ему автоматически не назначается. Кстати говоря, я ещё раз пересмотрел раздел продвинутого курса Евгения Гилёва, в котором он более кратко описывал работу в клиент-серверном режиме работы платформы, и он тоже показал и заострил внимание на том, если удалить соединение, тогда сеанс тоже удаляется. Но вот почему так происходит, тоже не объяснил. ((

5. А ещё Вы упомянули про некий ПУЛ СОЕДИНЕНИЙ. Что когда соединение больше не нужно, оно возвращается в пул соединений. Получается, что количество соединений ограничено, и находятся все они в этом пуле, и получается, что сначала соединение может быть назначено одному сеансу, затем по ненужности вернуться в пул, а через некоторое время назначиться другому сеансу?

1. Я говорю не про теорию, у меня на практике удаление соединения не приводит к удалению сеанса. Сеансу просто назначается другое соединение.
2. Причем тут 3 объекта. rphost общается с rmngr через соединение, эти соединения мы не видим в консоли.
3-4. Нельзя объединять сеанс и соединение, как минимум потому, что у соединения нет сеансовых данных. Как реализовано соединение в платформе на физическом уровне я не знаю, я не разработчик платформы, да если честно мне это все равно. На настройку кластера и оптимизацию это знание никак не повлияет. Если разработчики сделали 2 сущности, а не одну значит на то были причины, и мы можем либо тратить свое время на догадки почему они сделали именно так, либо просто принять это как есть и разобраться в том как это сейчас работает.
5. Да, все верно.

ОГО, ЧУДЕСА, в тонком клиенте и правда нету удаления сеанса, и назначается новое соединение сеансу.

У нас то просто УПП 1.3. Я все эксперименты из вашего курса и не только как правило делал на ней. А там основной режим работы: толстый клиент, обычное приложение. В обычном приложении почему-то при малейшем обрыве сети, соединение рвётся, сеанс удаляется. Даже если не надолго из сервера вытащить сетевой провод.

Да, толстый клиент работает так. Я и забыл уже что кто-то на толстом клиенте работает :)

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

PS: И да навести этим авантюристам из Москвы от души. Разрешаю) И стрелочники есть.

(1) DoctorRoza, Лучше всегда стараться делать запросы с левым соединением, как это делает СКД. Кстати если выполнить запрос по сумме вложенным, то он выполняется быстрее чем просто сделать левое соединение. (1) DoctorRoza, можно еще и полное соединение, только для номенклатуры придется использовать выражение:
Выбор Когда ТаблицаНоменклатураКоличество.Номенклатура Есть Null Тогда
ТаблицаНоменклатураСумма.Номенклатура
Иначе ТаблицаНоменклатураКоличество.Номенклатура
Конец
Вполне работоспособно (4) peterxx, Красивее выражение
ЕСТЬNULL(Таб1.Номеклатура,Таб2.Номенклатура) (1) DoctorRoza, Смотря чего требуют..
Можно левое соединение, но там есть своё НО, правильно сказал (2) mymyka,.
Можно внутреннее соединение - если нужно выбирать не все.. а согласно условию.
С левым соединением можно вывернуться, наложив условие на правую таблицу, в итоге получится внутреннее соединение.
Полное соединение не на всех СУБД хорошо отрабатывает, особенно если PostgreSQL, так что лучше разбить запрос и сделать через Объединение, если по всем полям, то ОБЪЕДИНИТЬ ВСЁ.
Для составного типа Данных есть команда: ВЫРАЗИТЬ.
(3) fly_men, - вложенный запрос не везде выигрывает))) (1) DoctorRoza, Наиболее быстрый через левое соединение, так как в этом случае используются индексы при выборке. (1) DoctorRoza, Включи профайлер посмотри замеры. Ты узнаешь, что оптимальнее. Форум-форумом, а скуль-скулем. Как построятся связи он тебе покажет в оптимальности съедаемого времени и ресурсов.

(1) Вопрос стоит простой "Левое соединение или Объединить + Сгруппировать По"

Спецификации "ВНУТРЕННЕЕ" и "ВНЕШНЕЕ" ни на что не влияют. Их ввели только для красоты.
А так есть четыре типа соединения :
СОЕДИНЕНИЕ (берем только записи удовлетворяющие условию)
ЛЕВОЕ СОЕДИНЕНИЕ (берем весь левый источник и пришпандориваем правый по условию)
ПРАВОЕ СОЕДИНЕНИЕ (берем весь правый источник и пришпандориваем правый по условию)
ПОЛНОЕ СОЕДИНЕНИЕ (берем оба источника и заполняем по условию)

СГРУППИРОВАТЬ ПО. Для чего нужна группировка в запросе? Для объединения в группу одинаковых полей таблицы и получения суммарных результатов по остальным. Группировка сворачивает одинаковые поля запроса в одно, уменьшая тем самым количество результирующих записей.

СГРУППИРОВАТЬ ПО выполняется быстрее, по простой причине.
Сгруппировать происходит за один проход построителя а при соединении минимум за два прохода. Сначала вычисляется одна таблица, потом вторая (к которой присоединена первая)
Следовательно, скорость выполнения может отличаться в 2 раза.
Вообще, рекомендуют использовать временные таблицы.
А 10 простых запросов, с последующим "СГРУППИРОВАТЬ ПО" выполнятся быстрее одного сложного с 10-ю соединениями.

(135) CaptainMorgan, возможно и так, но если посмотреть на данные с точки зрения кода, то не всегда так однозначно.

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

Что такое две выборки данных по 10к строк? Для современного сервера это миллисекунда-другая. Основное время тратиться на поиск оптимума чтений и первичное чтение данных.

Если говорить о массивах в миллион строк, каждая из которых в памяти занимает 100-200 байт, то, в среднем, для двух млн. строк нам надо 150 млн байт, т.к. 150 МБ. Пусть 200МБ - никого не удивить данными объемами. И вот тут уже становится видно, что и как работает.

Левое соединение выбирает первую строку из первой таблицы и ищет к ней по условию строку во второй (правой) таблице. И так для 1 млн строк. Если нет индекса по данному полю в правой таблице, то время выборки может быть весьма и весьма большим. Если индекс есть, то выборка будет осуществляться в среднем за Лог2(Н)/2 вычислений. Лог2(1 000 000) / 2 = 20 / 2 = 10. Т.е. мы имеем затраты на чтение и затраты на поиск строки во второй таблице, которые для современного сервера ниачом (у меня файл в один гиг - текст CSV с данными недействительных паспортов читается и упорядочивается за 16 сек на домашнем ноуте программой, написанной на С++ без использования базовых библиотек, чтение происходит из файлового потока f >> string).

Т.е. если нет индекса - объединение выигрывает, т.к. не надо ничего искать (об этом, кстати, я писал). Если индекс есть, то объединение весьма условно выиграет. Вот есть у вас массив результатов со строками. Система будет либо строить хеш, чтобы однозначно позиционироваться на строке, либо двоичное дерево результатов. В первом случае хеш на таких объемах скорее всего быстро выродится, что сведет на нет его эффективность, а во втором случае мы просто отращиваем двоичное дерево, при котором выигрыш будет в 2 раза, т.к. дерево наше будет расти, как, собственно, и логарифм по основанию два от его размера. Т.е. агрегация списка - это не один проход по общей выгрузке, а поиск следующего необработанного элемента среди уже обработанных. Да, в таком случае видится эффективность О(Лог2(Н)/2), что быстрее в 2 раза. Но нужно иметь ввиду, что основное время - это время чтения данных с диска, а не время выборки. Даже при миллионе строк время выборки может быть мало отличимо (типа 10 мс против 20 мс). Ну и во втором случае агрегируется сумма двух таблиц, т.е. дерево растет, но не до размера правой (второй) таблицы (как в случае левого соединение), а до суммы размеров таблицы. Что, в итоге, сводит мнимый выигрыш от объединения к нулю.


(1) Ещё один интересный аспект поставленного вопроса "Недавно проходил собеседование в одном нижегородской конторе на должность 1С-программиста. Был задан вопрос:"
Далее следует "хитрый" вопрос, потом ответ и "добитие" клиента.

Если внимательно рассмотреть эту ситуацию, то главное здесь не вопрос а реакция.
Замешкался - свободен.

Это обычные уловки грамотных HR-специалистов.
В реальности именно так и происходит. Но HR-щики плохо понимают психологию программиста.
Нормальный программист ни когда не будет "жарко" доказывать эффективность того или иного метода.
Он просто знает и точка.

По большому счёту, на текущем этапе развития компьютерной техники, "Левое соединение или Объединить + Сгруппировать По" не имеет значения. И если программист может и знает эти два метода, то верхом тупости не брать его на работу.

Эффективные условия запросов

Область применения: управляемое приложение, мобильное приложение, обычное приложение.

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

Поля основного условия в секциях ГДЕ, ПО и виртуальных таблицах должны быть проиндексированы. Основное условие может быть уточнено дополнительным условием, но объединять их следует только по И.

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

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

Дополнительное условие – это то, что объединено с основным условием по И и его составляющие могут быть любой сложности (НЕ, <>, +, -, /, *, функции и т.п.).

Основное условие должно содержать только такие операции, которые позволяют выполнять поиск по индексу:

  • для первого и всех используемых полей индекса, кроме последнего, только = и И;
  • для последнего или единственного используемого поля индекса допустимо использовать =, >, <, >=, <=, ПОДОБНО, МЕЖДУ, В, ИЛИ (приводимое к В);
  • нельзя использовать арифметические операции, функции, отрицания и неравенства.

Для условий в ГДЕ или в виртуальной таблице следует индексировать поля в основной таблице, из которой выполняется выборка.

Для условий в ПО ЛЕВОГО соединения следует индексировать поля в правой таблице.

Для условий в ПО ВНУТРЕННЕГО соединения следует индексировать поля в таблице с большим количеством записей.

Основное условие желательно строить таким образом, чтобы оно использовало индексы, которые автоматически создает платформа.

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

1.2. Если записей в таблице много и выполнить указанные выше требования невозможно, то можно попробовать:

  • преобразовать условия (см. п. 3, п. 4);
  • добавить в таблицу заранее вычисляемые индексированные поля, которые заполняются при записи в нее и используются вместо сложного условия;
  • если указанные выше рекомендации не помогли, то следует пересмотреть архитектуру решения так, чтобы можно было выполнить эти условия.

2.1. В основном условии оператор ИЛИ можно использовать только для последнего из используемых или единственного поля индекса, когда оператор ИЛИ можно заменить на оператор В.

ГДЕ
Таблица.Поле = &Значение1
ИЛИ Таблица.Поле = &Значение2

т.к. можно переписать при помощи оператора В (специально переписывать не нужно, можно оставить, как есть):

ГДЕ
Таблица.Поле В (&Значения)

ГДЕ
Таблица.Поле1 = &Значение1
ИЛИ Таблица.Поле2 = &Значение2

нельзя переписать при помощи "В", но можно переписать при помощи "ОБЪЕДИНИТЬ ВСЕ" (каждое поле Поле1 и Поле2 должны быть проиндексированы):

ГДЕ
Таблица.Поле1 = &Значение1

ГДЕ
Таблица.Поле2 = &Значение1

Примечание: заменить ИЛИ на ОБЪЕДИНИТЬ ВСЕ можно не всегда, убедитесь, что результат будет действительно тем же, что и при ИЛИ, перед тем, как применять.

2.2. В дополнительном условии оператор ИЛИ можно использовать без ограничений.

ГДЕ
Таблица.Поле1 = &Значение1 // Основное условие (использует индекс)
И // Дополнительное условие (можно использовать ИЛИ)
(Таблица.Поле2 = &Значение2 ИЛИ Таблица.Поле3 = &Значение3)

ГДЕ
(Таблица.Поле1 = &Значение1 ИЛИ Таблица.Поле1 = &Значение2)
И
(Таблица.Поле2 = &Значение3 ИЛИ Таблица.Поле2 = &Значение4)

т.к. можно переписать при помощи В (специально переписывать не нужно, можно оставить, как есть):

ГДЕ
Таблица.Поле1 В (&Значения1) // Основное условие
И Таблица.Поле2 В (&Значения2) // Дополнительное условие (или наоборот)

3. Оператор ПОДОБНО

В основном условии для последнего из используемых или единственного поля индекса можно использовать оператор ПОДОБНО. Функции работы со строками, в некоторых случаях, можно привести к оператору ПОДОБНО и использовать его в основном условии.

ГДЕ
ПОДСТРОКА(Таблица.Поле, 1, 6) = "строка"

ГДЕ
Таблица.Поле ПОДОБНО "строка%"

ГДЕ
ПОДСТРОКА(Таблица.Поле, 3, 6) = "строка"

ГДЕ
Таблица.Поле ПОДОБНО "__строка%" // Литерал не должен начинаться с символов "_" или "%"

Добавить новое вычисляемое при записи в таблицу поле, которое будет содержать фрагмент ПОДСТРОКА(Таблица.Поле, 3, 6). Проиндексировать это поле и искать по следующему условию:

ГДЕ
Таблица.ВычисляемоеПоле ПОДОБНО "строка%"

4. Оператор МЕЖДУ

В основном условии для последнего из используемых или единственного поля индекса можно использовать оператор МЕЖДУ. Функции работы с датой, в некоторых случаях, можно привести к оператору МЕЖДУ и использовать его в основном условии.

ГДЕ
МЕСЯЦ(Таблица.Поле) = 1

ГДЕ
Таблица.Поле МЕЖДУ &ДатаНачалаМесяца И &ДатаКонцаМесяца

Например, ДатаНачалаМесяца=01.01.2016, ДатаКонцаМесяца=31.01.2016 23:59:59

5. Выражение ВЫБОР

Выражение ВЫБОР можно использовать только в дополнительных условиях.

ГДЕ
Таблица.Поле1 = &Значение1 // Основное условие (использует индекс)
И // Дополнительное условие (можно использовать ВЫБОР)
ВЫБОР
КОГДА Таблица.Поле2 = &Значение2
ТОГДА Таблица.Поле3 = &Значение3
ИНАЧЕ Таблица.Поле4 = &Значение4
КОНЕЦ

ГДЕ
ВЫБОР // Основное условие (поиск по индексу использоваться не будет)
КОГДА Таблица.Поле2 = &Значение2
ТОГДА Таблица.Поле3 = &Значение3
ИНАЧЕ Таблица.Поле4 = &Значение4
КОНЕЦ

6. Арифметические операции

Арифметические операции над полями можно выполнять только в дополнительных условиях.

ГДЕ
Таблица.Поле1 = &Значение1 // Основное условие (использует индекс)
И // Дополнительное условие (можно выполнять арифметические операции)
Таблица.Поле2 - 1 > 0

ГДЕ
Таблица.Поле1 - 1 > 0 // Основное условие (поиск по индексу невозможен)

7. Если в конфигурации описано несколько ролей с разным ограничением доступа на уровне записей (RLS), то не следует назначать одному пользователю более одной такой роли. Если один пользователь будет включен, например, в две роли с RLS - бухгалтер и кадровик, то при выполнении всех его запросов к их условиям будут добавляться условия обоих RLS с использованием логического ИЛИ. Таким образом, даже если в исходном запросе нет условия ИЛИ, оно появится там после добавления условий RLS. Такой запрос так же может выполняться неоптимально - медленно и с избыточными блокировками.

И это достаточно распространенная проблема.

Часто при написании запросов разработчик стремится просто как можно быстрее выполнить задачу в соответствии с постановкой.

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

Видео 01:

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

Однако использование этого оператора в запросах содержит ряд подводных камней.

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


Видео 02:
О вреде использования математических вычислений в условиях запроса

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

В этом уроке рассмотрим пример, когда оптимизатор СУБД выбирает неоптимальный план выполнения запроса из-за обычной операции сложения.


Видео 03:

Многие задачи по выборке данных решаются с помощью проверки того, что нужные элементы не входят в некоторый список (это зачастую подзапрос). И такие запросы становятся проблемой, когда данные в ИБ накапливаются, поскольку СУБД их не может эффективно выполнять.

В видео показано, почему такая проблема возникает и как ее решить.


Видео 04:
Непопадание в индекс при использовании встроенных функций языка запросов

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

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

Читайте также: