Всем привет! нужна помощь.

В компании включен RLS, но необходимо, чтобы поиск в подборе происходил достаточно быстро. Запрос вывода в динамический список, уже несколько раз изменялся, убирались лишние на текущий момент таблицы, теперь дошло и до RLS. Через сиквел мы видим, что при построении запроса поиска платформа подтягивает таблицы ограничении RLS'а. Нашли роль, которая осуществляет подстановку запроса, в УТ 11 это "ЧтениеОстатковДоступныхТоваров". Если мы коментим ограничение доступа у регистра накопления "СвободныеОстатки", то о чудо, при построения запроса поиска таблицы нету. Было принято решение добавить условие в ограничение доступа и через параметр сеанса включать/выключать данное ограничение. Т.е. при открытии/закрытии формы мы меняем параметр сеанса.

Создал параметр, добавил условие, добавил инициализацию при запуске, добавил код изменения параметр сеанса в подборе при открытии/закрытии формы. НО, ничего не поменялось, т.е. если мы меняем при запуске булево с ложь на истина, то да, таблица не добавляется. Если мы меняем при открытии/закрытии формы, нет. На мысль пришло то что необходимо при открытии/закрытии повторно инициализировать параметр сеанса. Так же нашел, что если мы отключаем RLS, то на лету (без перезахода) отключается подстановка таблицы. Посмотрел код при отключении/включении RLS, нашел, при изменении параметра, программа лезет в общий модуль "УправлениеДоступомСлужебный" в процедуру "УстановкаПараметровСеанса". Сделал обращение при открытии/закрытии формы по аналогии, добавил в эту процедуру свой параметр, прописал установку этого параметра так же как и остальные. И...... ничего не поменялось... Есть предложения куда еще можно заглянуть?

В роли прописано вот так:

```1c
    #Если НЕ &ЛМ_НеИспользоватьRLS #Тогда
    #Если &ОграничениеДоступаНаУровнеЗаписейУниверсально #Тогда
    #ДляРегистра("ИдентификаторыОбъектовМетаданных.РегистрНакопленияСвободныеОстатки", "Склад", ", ", ", ")
    #Иначе
    #ПоЗначениям( "РегистрНакопления.СвободныеОстатки","Чтение",",
    "Склады","Склад", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", "," )
    #КонецЕсли
    #КонецЕсли

    в Общем модуле вот так:

    &Вместо("УстановкаПараметровСеанса")
    Процедура ЛМ_УстановкаПараметровСеанса(ИмяПараметра, УстановленныеПараметры)

    //на всякий случай скопировал весь модуль
    //Если ИмяПараметра = "ЛМ_НеИспользоватьRLS" Тогда
    ОграничениеЛМ_НеИспользоватьRLS = Константы.ЛМ_НеИспользоватьRLS.Получить();
    ПараметрыСеанса.ЛМ_НеИспользоватьRLS = ОграничениеЛМ_НеИспользоватьRLS;
    УстановленныеПараметры.Добавить("ЛМ_НеИспользоватьRLS");
    //КонецЕсли;
    .......

    Обращение в эту процедуру вот так:

    Процедура ПриИзмененииЛМ_НеИспользоватьRLS(ОграничениеДоступаНаУровнеЗаписейВключено) Экспорт

    УстановитьПривилегированныйРежим(Истина);

    Константы.ЛМ_НеИспользоватьRLS.Установить(ОграничениеДоступаНаУровнеЗаписейВключено);

    УстановленныеПараметры = Новый Массив;
    УстановкаПараметровСеанса(", УстановленныеПараметры);

    КонецПроцедуры
```

Из формы произвожу обращение:

```1c
    &НаСервере
    Процедура ЛМ_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    НачатьТранзакцию();

    УстановитьПривилегированныйРежим(Истина);
    УправлениеДоступомСлужебный.ПриИзмененииЛМ_НеИспользоватьRLS(Истина);
    УстановитьПривилегированныйРежим(Ложь);
    ЗафиксироватьТранзакцию();
    КонецПроцедуры
```

при закрытии на севере так же только параметр "Ложь"

p.s. отключить RLS не предлагать=)))
---
еще раз спасибо за помощь. Я реализовал через константу.

```1c
    Процедура УстановкаПараметровСеанса(ИмяПараметра, УстановленныеПараметры) Экспорт
    //УстановитьПривилегированныйРежим(Истина);
    Если ИмяПараметра = "ЛМ_ОтключениеRLS" Тогда

    ТекстИзКонстанты = Константы.ЛМ_ПользователиКоторымОтключатьRLSНаВремя.Получить();
    Если СтрНайти(ТекстИзКонстанты, " + Строка(ПользователиИнформационнойБазы.ТекущийПользователь()) + ";") = 0 Тогда
    ПараметрыСеанса.ЛМ_ОтключениеRLS = Ложь;
    Иначе
    ПараметрыСеанса.ЛМ_ОтключениеRLS = Истина;
    КонецЕсли;
    УстановленныеПараметры.Добавить("ЛМ_ОтключениеRLS");
    КонецЕсли;

    КонецПроцедуры
```

На форме:

```1c
    &НаСервере
    Процедура ЛМ_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)

    УстановитьПривилегированныйРежим(Истина);
    Константы.ЛМ_ПользователиКоторымОтключатьRLSНаВремя.Установить(" + Строка(ПользователиИнформационнойБазы.ТекущийПользователь()) + ";");
    УстановитьПривилегированныйРежим(Ложь);

    КонецПроцедуры

    &НаСервере
    Процедура ЛМ_ПриЗакрытииПослеНаСервере()

    УстановитьПривилегированныйРежим(Истина);
    ТекстИзКонстанты = Константы.ЛМ_ПользователиКоторымОтключатьRLSНаВремя.Получить();
    ТекстИзКонстанты = СтрЗаменить(ТекстИзКонстанты, " + Строка(ПользователиИнформационнойБазы.ТекущийПользователь()) + ";", ");
    Константы.ЛМ_ПользователиКоторымОтключатьRLSНаВремя.Установить(ТекстИзКонстанты);
    УстановитьПривилегированныйРежим(Ложь);

    КонецПроцедуры
```

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

По поводу Суриката, таблица "Номенклатуры" у нас достаточно большая (более 50к записей) так же происходит левое соединение с двумя таблицами ограничений, поэтому выполняется в 10 раз дольше. Чтобы этого не было, мы пытаемся минимизировать обращений запроса.
---
Вы бы план запроса проблемного показали или хотя бы сам запрос ... Там много настроек, которые влияют на итоговый запрос дин. списка.
Вы уверены, что проблема в RLS? Или вы имеете ввиду, что у вас при RLS есть скан таблицы вместо поиска по индексу?
---
я не мучаю РЛС, а перехватываю создание форм в расширении и модифицирую запрос динамического списка по ряду условий - это проще, дешевле и понятнее чем охапка костылей.

примерно так же поступают в типовых в основной конфигурации.
---
прошу прочитать еще раз начала основного текста. Запрос динамического списка и так сокращен на сколько можно. Дальше платформа производит подставление, т.к. при отладке если посмотреть на запрос динамического списка, то он такой же как мы его туда вогнали. Но если смотрим момент обращение в БД через SQL Server Profiler мы видим, что к основному запроса добавляется таблица ограничений, т.е. еще одна таблица из справочника и одна из регистра сведений.
---
тогда героически боритесь со способом обмана РЛС - я такой борьбы избегаю, очень дорого)
---
пока приходится=) жду может кто еще сталкивался с данной проблемой...
---
Вы как-то усложнили работу с параметром сеанса, возможно поэтому Ваш трюк и не удался: где-то что-то упустили. У меня получилось осуществить задуманное Вами с использованием параметра сеанса.

Вот какие есть замечания:

1) Вы некорректно инициализируете значение параметра сеанса. Нет необходимости копировать всю процедуру установки параметров сеанса целиком. Равно как и непосредственно вызывать ее. В конфигурации на базе БСП для этого в процедуре "ПриДобавленииОбработчиковУстановкиПараметровСеанса" общего модуля "ОбщегоНазначенияПереопределяемый" описывается собственный обработчик для своих параметров сеанса:

```1c
    Обработчики.Вставить("ИмяПараметраСеанса", "МойОбщийМодуль.УстановкаПараметровСеанса");
```
Коли Вы используете расширения, добавьте данную процедуру в расширение с директивой &После и добавьте это описание обработчика. А затем в своем собственном модуле "МойОбщийМодуль" описываете свою процедуру "УстановкаПараметровСеанса" для инициализации собственных параметров сеанса:

```1c
    Процедура УстановкаПараметровСеанса(ИмяПараметра, УстановленныеПараметры) Экспорт

    Если ИмяПараметра = "ИмяПараметраСеанса" Тогда
    ПараметрыСеанса.ИмяПараметраСеанса= Константы.МояКонстанта.Получить();
    УстановленныеПараметры.Добавить("ИмяПараметраСеанса");
    КонецЕсли;

    КонецПроцедуры
```
Готово. При первом обращении к параметру сеанса будет вызвана данная процедура инициализации его значения. Подробнее об определении обработчиков установки параметров сеанса почитайте в описании к процедуре "ПриДобавленииОбработчиковУстановкиПараметровСеанса" модуля "ОбщегоНазначенияПереопределяемы" и на ИТС.

2) Некорректным мне кажется и присваивание нового значения параметру сеанса при открытии формы. Раз Вы используете значение константы для инициализации, то вместо непосредственного вызова процедуры "УстановкаПараметровСеанса" лучше просто очищать значение параметра сеанса:

```1c
    Константы.МояКонстанта.Установить(Истина/Ложь);
    ОчищаемыеПараметры = Новый Массив;
    ОчищаемыеПараметры.Добавить("ИмяПараметраСеанса");
    ПараметрыСеанса.Очистить(ОчищаемыеПараметры);
```
Больше ничего делать не нужно. При следующей попытки обращения к значению параметра сеанса он вновь будет инициализирован значением константы в обработчике, который я описал в п.1.

3) Ну и использование константы для хранения и инициализации значения Вашего параметра сеанса выглядит неудачным решением. Значение константы - одно на всю информационную базу. Фактически, пока один пользователь работает с формой подбора, все остальные пользователи также получают привилегированный режим для работы с таблицей свободных остатков. Я предлагаю, во-первых, отказаться от использования константы вовсе. Соответственно инициализировать параметр сеанса по умолчанию значением, запрещающим привилегированный режим с таблицей остатков. И во-вторых, в форме подбора как и раньше включить и выключать флаг, хранимый в параметре сеанса, непосредственным присваиванием нужного значения:

```1c
    УстановитьПривилегированныйРежим(Истина);
    ПараметрыСеанса.ИмяПараметраСеанса = Истина/Ложь;
```
---
спасибо за ответ!

Я использовал константу по аналогии с включением/выключением RLS т к напрямую не получалось, т. е. При открытии формы, я производил обращение как вы написали в конце, параметр менялся все ок, но когда производился запрос к БД (смотрел через вьюер SQL), то таблицы все равно подставлялись. Если необходимо выслать примеры запросов БД, могу это сделать.

Я не мог понять, почему даже при открытой формы подбора, если включаешь/отключаешь RLS, то «налету» подставляется/убирается таблицы проверки.

Сегодня попробую как вы посоветовали, дальше отпишусь.
---
нет. Не работает....

Пишу что я сейчас сделал. Я снес все. Заново добавил условие в правиле

```1c
    #Если НЕ &ЛМ_ОтключениеRLS #Тогда
    #Если &ОграничениеДоступаНаУровнеЗаписейУниверсально #Тогда
    #ДляРегистра("ИдентификаторыОбъектовМетаданных.РегистрНакопленияСвободныеОстатки", "Склад", ", ", ", ")
    #Иначе
    #ПоЗначениям( "РегистрНакопления.СвободныеОстатки","Чтение",",
    "Склады","Склад", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", "," )
    #КонецЕсли
    #КонецЕсли
```

Добавил:

```1c
    &После("ПриДобавленииОбработчиковУстановкиПараметровСеанса")
    Процедура ЛМ_ПриДобавленииОбработчиковУстановкиПараметровСеанса(Обработчики)

    Обработчики.Вставить("ЛМ_ОтключениеRLS", "ЛМ_ОбщийМодульСервер.УстановкаПараметровСеанса");

    КонецПроцедуры
```

Добавил:

```1c
    Процедура УстановкаПараметровСеанса(ИмяПараметра, УстановленныеПараметры) Экспорт

    Если ИмяПараметра = "ЛМ_ОтключениеRLS" Тогда
    ПараметрыСеанса.ЛМ_ОтключениеRLS = Ложь;
    УстановленныеПараметры.Добавить("ЛМ_ОтключениеRLS");
    КонецЕсли;

    КонецПроцедуры
```

Добавил:

```1c
    &НаСервере
    Процедура ЛМ_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)

    УстановитьПривилегированныйРежим(Истина);
    ПараметрыСеанса.ЛМ_ОтключениеRLS = Истина;
    УстановитьПривилегированныйРежим(Ложь);

    КонецПроцедуры
```
...

И нет, не работает, т.е. в запросе все равно присутствуют таблицы...

(7)
Вот изначальный запрос:

```1c
    Результат="ВЫБРАТЬ
    | СправочникНоменклатура.Ссылка КАК Ссылка,
    |СправочникНоменклатура.Синонимы КАК Синонимы,
    |СправочникНоменклатура.Марка КАК Бренд,
    |СправочникНоменклатура.ЛМ_АртикулыПоставщиков КАК АртикулыПоставщиков,
    | СправочникНоменклатура.Артикул КАК Артикул,
    | СправочникНоменклатура.Код КАК Код,
    | СправочникНоменклатура.Наименование КАК Наименование,
    | СправочникНоменклатура.Ссылка КАК Номенклатура,
    | СправочникНоменклатура.Ссылка КАК ЭлементСписка,
    | СправочникНоменклатура.ВидНоменклатуры КАК ВидНоменклатуры,
    | СправочникНоменклатура.ЛМ_ЦеновыеКатегорииДляКраски КАК ЦеновыеКатегорииДляКраски,
    | СправочникНоменклатура.ТипНоменклатуры КАК ТипНоменклатуры,
    | СправочникНоменклатура.ЛМ_ЕдиницаИзмеренияДляПодбора КАК ЕдиницаИзмерения,
    | СправочникНоменклатура.Качество КАК Качество,
    | СправочникНоменклатура.ИспользованиеХарактеристик КАК ИспользованиеХарактеристик,
    | &ВидыЦен КАК ВидЦены,
    | ВЫРАЗИТЬ(ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0) КАК ЧИСЛО(31,2)) КАК Цена,
    | ВЫРАЗИТЬ(ЕСТЬNULL(СвободныеОстатки.ВНаличииОстаток, 0) КАК ЧИСЛО(15, 3)) КАК ВНаличииОстаток,
    | ЕСТЬNULL(СвободныеОстатки.ВНаличииОстаток, 0) КАК ВНаличииВБазовыхЕдиницах,
    | ВЫРАЗИТЬ(ЕСТЬNULL(СвободныеОстатки.ВНаличииОстаток, 0) - ЕСТЬNULL(СвободныеОстатки.ВРезервеПодЗаказОстаток, 0) -
    | ЕСТЬNULL(СвободныеОстатки.ВРезервеСоСкладаОстаток, 0) + ЕСТЬNULL(ОстаткиИзЗаказов.Количество, 0)
    |КАК ЧИСЛО(15, 3)) КАК Доступно
    | ИЗ
    |
    | Справочник.Номенклатура КАК СправочникНоменклатура
    | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
    | КОНЕЦПЕРИОДА(&Дата, День),
    | ВидЦены = &ВидыЦен
    | И Характеристика = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
    | {(Номенклатура).* КАК Номенклатура}
    | ) КАК ЦеныНоменклатуры
    | ПО (ЦеныНоменклатуры.Номенклатура = СправочникНоменклатура.Ссылка)
    | И (ЦеныНоменклатуры.Характеристика = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка))
    | И (ЦеныНоменклатуры.ВидЦены = &ВидыЦен)
    |
    |
    | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.СвободныеОстатки.Остатки(
    | ,
    | Склад = &Склад
    | И Характеристика = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
    | {(Номенклатура).* КАК Номенклатура}
    | ) КАК СвободныеОстатки
    | ПО (СвободныеОстатки.Склад = &Склад)
    | И (СвободныеОстатки.Номенклатура = СправочникНоменклатура.Ссылка)
    | И (СвободныеОстатки.Характеристика = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка))
    |
    | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДоступныеОстаткиПланируемыхПоступлений КАК ОстаткиИзЗаказов
    | ПО (ОстаткиИзЗаказов.Склад = &Склад)
    | И (ОстаткиИзЗаказов.Характеристика = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка))
    | И (ОстаткиИзЗаказов.ДатаДоступности = ДАТАВРЕМЯ(1, 1, 1))
    | И (ОстаткиИзЗаказов.Номенклатура = СправочникНоменклатура.Ссылка)
    | И (ОстаткиИзЗаказов.Количество < 0)
    |
    | ГДЕ
    |
    | НЕ СправочникНоменклатура.ЭтоГруппа
    |
    |
    |{ГДЕ
    | (1 В
    | (ВЫБРАТЬ ПЕРВЫЕ 1
    | 1
    | ИЗ
    | РегистрСведений.НоменклатураСегмента КАК Сегменты
    | ГДЕ
    | Сегменты.Номенклатура = СправочникНоменклатура.Ссылка
    | И Сегменты.Сегмент = &СегментНоменклатуры))}";
```

Вот так выглядит данный запрос при поиске в SQL Server Profiler (прошу обратить внимание на "EXISTS", данные таблицы подставляются, если RLS включен)

```1c
    exec sp_executesql N'SEL ECT
    T29._IDRRef,
    T29._Description
    FR OM dbo._Reference270 T29
    LEFT OUTER JOIN (SEL ECT
    T33._Fld17496RRef AS Fld17496RRef,
    T33._Fld17497RRef AS Fld17497RRef,
    T33._Fld17495RRef AS Fld17495RRef
    FR OM (SEL ECT
    T32._Fld17495RRef AS Fld17495RRef,
    T32._Fld17496RRef AS Fld17496RRef,
    T32._Fld17497RRef AS Fld17497RRef,
    MAX(T32._Period) AS MAXPERIOD_
    FR OM dbo._InfoRg17494 T32
    WHERE ((T32._Fld1354 = @P1)) AND (T32._Period <= @P2 AND (((T32._Fld17497RRef = @P3) AND (T32._Fld17496RRef = @P4))))
    GROUP BY T32._Fld17495RRef,
    T32._Fld17496RRef,
    T32._Fld17497RRef) T31
    INNER JOIN dbo._InfoRg17494 T33
    ON T31.Fld17495RRef = T33._Fld17495RRef AND T31.Fld17496RRef = T33._Fld17496RRef AND T31.Fld17497RRef = T33._Fld17497RRef AND T31.MAXPERIOD_ = T33._Period
    WHERE (T33._Fld1354 = @P5)) T30
    ON (((T30.Fld17495RRef = T29._IDRRef) AND (T30.Fld17496RRef = @P6)) AND (T30.Fld17497RRef = @P7))
    LEFT OUTER JOIN (SEL ECT
    T35._Fld19334RRef AS Fld19334RRef,
    T35._Fld19336RRef AS Fld19336RRef,
    T35._Fld19335RRef AS Fld19335RRef,
    T35._Fld19337 AS Fld19337Balance_,
    T35._Fld19338 AS Fld19338Balance_,
    T35._Fld19339 AS Fld19339Balance_
    FR OM dbo._AccumRgT19341 T35
    WHERE (((T35._Fld1354 = @P8)) AND (EXISTS(SEL ECT
    0x01 AS Q_001_F_000_
    FR OM dbo._Reference216 T36
    INNER JOIN dbo._Reference175 T37
    ON (((T36._Fld23442 = @P9) AND EXISTS(SEL ECT
    0x01 AS Q_002_F_000_
    FR OM dbo._InfoRg17048 T38
    WHERE ((T38._Fld1354 = @P10)) AND ((T38._Fld17049_TYPE = 0x08 AND T38._Fld17049_RTRef = 0x000000D8 AND T38._Fld17049_RRRef = T36._IDRRef) AND (T38._Fld17050RRef = T37._IDRRef)))) AND 0x000000AF = 0x000000AF AND T37._IDRRef IN
    (SELECT
    T39._Reference175_IDRRef AS Q_003_F_000RRef
    FR OM dbo._Reference175_VT22490 T39
    INNER JOIN dbo._InfoRg16553 T40
    ON ((T40._Fld16555_TYPE = 0x08 AND T40._Fld16555_RTRef = 0x00000139 AND T40._Fld16555_RRRef = @P11) AND (T40._Fld16554_TYPE = T39._Fld22492_TYPE AND T40._Fld16554_RTRef = T39._Fld22492_RTRef AND T40._Fld16554_RRRef = T39._Fld22492_RRRef))
    WHERE ((T39._Fld1354 = @P12)) AND (T40._Fld1354 = @P13)))
    WHERE ((T37._Fld1354 = @P14)) AND ((0x08 <> 0x01))))) AND (T35._Period = @P15 AND (((T35._Fld19336RRef = @P16) AND (T35._Fld19335RRef = @P17))) AND (T35._Fld19337 <> @P18 OR T35._Fld19338 <> @P19 OR T35._Fld19339 <> @P20) AND (T35._Fld19337 <> @P21 OR T35._Fld19338 <> @P22 OR T35._Fld19339 <> @P23))) T34
    ON (((T34.Fld19336RRef = @P24) AND (T34.Fld19334RRef = T29._IDRRef)) AND (T34.Fld19335RRef = @P25))
    LEFT OUTER JOIN dbo._InfoRg14493 T41
    ON ((((((T41._Fld14496RRef = @P26) AND (T41._Fld14495RRef = @P27)) AND (T41._Fld14497 = @P28)) AND (T41._Fld14494RRef = T29._IDRRef)) AND (T41._Fld14498 < @P29))) AND (T41._Fld1354 = @P30)
    WH ERE ((T29._Fld1354 = @P31)) AND ((T29._Folder) = 0x01 AND ((((((T29._Fld24341 LIKE @P32 ESCAPE ''/'') OR (T29._Fld33502 LIKE @P33 ESCAPE ''/'')) OR (T29._Fld33736 LIKE @P34 ESCAPE ''/'')) OR (T29._Description LIKE @P35 ESCAPE ''/'')) OR (T29._Fld33516 LIKE @P36 ESCAPE ''/'')) OR (T29._Fld33621 LIKE @P37 ESCAPE ''/'')) AND (T29._IDRRef IN (@P38, @P39)))',N'@P1 numeric(10),@P2 datetime2(3),@P3 varbinary(16),@P4 varbinary(16),@P5 numeric(10),@P6 varbinary(16),@P7 varbinary(16),@P8 numeric(10),@P9 nvarchar(4000),@P10 numeric(10),@P11 varbinary(16),@P12 numeric(10),@P13 numeric(10),@P14 numeric(10),@P15 datetime2(3),@P16 varbinary(16),@P17 varbinary(16),@P18 numeric(10),@P19 numeric(10),@P20 numeric(10),@P21 numeric(10),@P22 numeric(10),@P23 numeric(10),@P24 varbinary(16),@P25 varbinary(16),@P26 varbinary(16),@P27 varbinary(16),@P28 datetime2(3),@P29 numeric(10),@P30 numeric(10),@P31 numeric(10),@P32 nvarchar(4000),@P33 nvarchar(4000),@P34 nvarchar(4000),@P35 nvarchar(4000),@P36 nvarchar(4000),@P37 nvarchar(4000),@P38 varbinary(16),@P39 varbinary(16)',0,'4019-08-19 23:59:59',0x9107005056B17BE811E8FEC489DA96B7,0x00000000000000000000000000000000,0,0x00000000000000000000000000000000,0x9107005056B17BE811E8FEC489DA96B7,0,N'РегистрНакопления.СвободныеОстатки',0,0x911A005056B1CDF811E9B9BBD00727A3,0,0,0,'5999-11-01 00:00:00',0x00000000000000000000000000000000,0x00000000000000000000000000000000,0,0,0,0,0,0,0x00000000000000000000000000000000,0x00000000000000000000000000000000,0x00000000000000000000000000000000,0x00000000000000000000000000000000,'2001-01-01 00:00:00',0,0,0,N'%клей%',N'%клей%',N'%клей%',N'%клей%',N'%клей%',N'%клей%',0xB81F005056B6320D11E9503877CAF997,0xB840005056B6F8A211E956829351CA4D
```

Вот так выглядит данный запрос при поиске в SQL Server Profiler (прошу обратить внимание на "EXISTS", данные таблицы нету, т.к. RLS отключен):

```1c
    exec sp_executesql N'SELECT
    T17._IDRRef,
    T17._Description
    FR OM dbo._Reference270 T17
    LEFT OUTER JOIN (SELECT
    T21._Fld17496RRef AS Fld17496RRef,
    T21._Fld17497RRef AS Fld17497RRef,
    T21._Fld17495RRef AS Fld17495RRef
    FR OM (SELECT
    T20._Fld17495RRef AS Fld17495RRef,
    T20._Fld17496RRef AS Fld17496RRef,
    T20._Fld17497RRef AS Fld17497RRef,
    MAX(T20._Period) AS MAXPERIOD_
    FR OM dbo._InfoRg17494 T20
    WH ERE ((T20._Fld1354 = @P1)) AND (T20._Period <= @P2 AND (((T20._Fld17497RRef = @P3) AND (T20._Fld17496RRef = @P4))))
    GROUP BY T20._Fld17495RRef,
    T20._Fld17496RRef,
    T20._Fld17497RRef) T19
    INNER JOIN dbo._InfoRg17494 T21
    ON T19.Fld17495RRef = T21._Fld17495RRef AND T19.Fld17496RRef = T21._Fld17496RRef AND T19.Fld17497RRef = T21._Fld17497RRef AND T19.MAXPERIOD_ = T21._Period
    WH ERE (T21._Fld1354 = @P5)) T18
    ON (((T18.Fld17495RRef = T17._IDRRef) AND (T18.Fld17496RRef = @P6)) AND (T18.Fld17497RRef = @P7))
    LEFT OUTER JOIN (SELECT
    T23._Fld19334RRef AS Fld19334RRef,
    T23._Fld19336RRef AS Fld19336RRef,
    T23._Fld19335RRef AS Fld19335RRef,
    T23._Fld19337 AS Fld19337Balance_,
    T23._Fld19338 AS Fld19338Balance_,
    T23._Fld19339 AS Fld19339Balance_
    FR OM dbo._AccumRgT19341 T23
    WH ERE ((T23._Fld1354 = @P8)) AND (T23._Period = @P9 AND (((T23._Fld19336RRef = @P10) AND (T23._Fld19335RRef = @P11))) AND (T23._Fld19337 <> @P12 OR T23._Fld19338 <> @P13 OR T23._Fld19339 <> @P14) AND (T23._Fld19337 <> @P15 OR T23._Fld19338 <> @P16 OR T23._Fld19339 <> @P17))) T22
    ON (((T22.Fld19336RRef = @P18) AND (T22.Fld19334RRef = T17._IDRRef)) AND (T22.Fld19335RRef = @P19))
    LEFT OUTER JOIN dbo._InfoRg14493 T24
    ON ((((((T24._Fld14496RRef = @P20) AND (T24._Fld14495RRef = @P21)) AND (T24._Fld14497 = @P22)) AND (T24._Fld14494RRef = T17._IDRRef)) AND (T24._Fld14498 < @P23))) AND (T24._Fld1354 = @P24)
    WH ERE ((T17._Fld1354 = @P25)) AND ((T17._Folder) = 0x01 AND ((((((T17._Fld24341 LIKE @P26 ESCAPE ''/'') OR (T17._Fld33502 LIKE @P27 ESCAPE ''/'')) OR (T17._Fld33736 LIKE @P28 ESCAPE ''/'')) OR (T17._Description LIKE @P29 ESCAPE ''/'')) OR (T17._Fld33516 LIKE @P30 ESCAPE ''/'')) OR (T17._Fld33621 LIKE @P31 ESCAPE ''/'')) AND (T17._IDRRef IN (@P32, @P33)))',N'@P1 numeric(10),@P2 datetime2(3),@P3 varbinary(16),@P4 varbinary(16),@P5 numeric(10),@P6 varbinary(16),@P7 varbinary(16),@P8 numeric(10),@P9 datetime2(3),@P10 varbinary(16),@P11 varbinary(16),@P12 numeric(10),@P13 numeric(10),@P14 numeric(10),@P15 numeric(10),@P16 numeric(10),@P17 numeric(10),@P18 varbinary(16),@P19 varbinary(16),@P20 varbinary(16),@P21 varbinary(16),@P22 datetime2(3),@P23 numeric(10),@P24 numeric(10),@P25 numeric(10),@P26 nvarchar(4000),@P27 nvarchar(4000),@P28 nvarchar(4000),@P29 nvarchar(4000),@P30 nvarchar(4000),@P31 nvarchar(4000),@P32 varbinary(16),@P33 varbinary(16)',0,'4019-08-19 23:59:59',0x9107005056B17BE811E8FEC489DA96B7,0x00000000000000000000000000000000,0,0x00000000000000000000000000000000,0x9107005056B17BE811E8FEC489DA96B7,0,'5999-11-01 00:00:00',0x00000000000000000000000000000000,0x00000000000000000000000000000000,0,0,0,0,0,0,0x00000000000000000000000000000000,0x00000000000000000000000000000000,0x00000000000000000000000000000000,0x00000000000000000000000000000000,'2001-01-01 00:00:00',0,0,0,N'%монтаж%',N'%монтаж%',N'%монтаж%',N'%монтаж%',N'%монтаж%',N'%монтаж%',0xB840005056B6F8A211E945E4FE1512D7,0xB81F005056B6320D11E959E0B9D51E7B
```
---
Еще один возможно глупый вопрос. А не может ли оказаться, что проверка прав выполняется не для регистра накопления "СвободныеОстатки", а для регистра сведений "ДоступныеОстаткиПланируемыхПоступлений"? Какие роли Вы исправляли? И проверяли ли, какие именно таблицы в используются в конечном SQL-запросе?
---
Если закомментировать правила в указанной роли, то таблицы не добавляются => именно СвободныеОстатки=)))
---
все оказалось сложнее, чем я думал....

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

Пока мысля сделать константу и туда записывать пользователя как строка через разделитель и проверять при вызове "УстановкаПараметровСеанса"...
---
Интересно. Т.е. получается, что при создании на сервере не смотря на нашу инструкцию параметр сеанса не был инициализирован? И инициализируется он только при начале использования в РЛС? Очень неожиданно, но можно попробовать подстроиться: прежде, чем установить параметру сеанса значение при создании формы, попробуйте прочитать это значение. Т.о. будет инициирована инициализация параметра, а уже после этого Вы установите ему нужное значение.
---
Форма "ПодборТоваровВДокументПродажи"

Как только я пишу текст в поиске он выпадает вот так (см. Рис). И если я пытаюсь проверить условием, выпадает ошибка.
---
Сейчас ставлю Истина дефолтом, т.к. проверял запрос=)
---
Ну здесь то ошибка по понятным причинам. :) Вы пытаетесь прочитать значение параметра сеанса, но для этого системе нужно его инициализировать. А чтобы инициализировать, нужно выполнить тот самый код, который Вы прервали отладчиком.
---
да, это я тоже понимаю, но получается, что необходим внешний источник, как константа, которая будет определять истина и ложь. Но просто булево константу я не могу поставить, т.к. распространится на всех... поэтому я и написал записывать пользователя как строка с разделителями, чтобы понимать кому включать, кому выключать.
---
Не согласен. Зачем внешний источник?

Попробовал воспроизвести Вашу ситуацию по Вашему же описанию из (9). Использовал демо-базу 11.4.6.188 на платформе 8.3.14.1779. Все изменения вносил непосредственно в конфигурацию, расширения не использовал. Во вложении отчет о сравнении, типовой и доработанной, чтобы видеть все мои изменения.

Профайлер не смотрел пока. Доработал роль немного иначе:

```1c
    #Если НЕ &ЛМ_ОтключениеRLS #Тогда

    Ограничение_включилось: что-то пошло не так

    #Если &ОграничениеДоступаНаУровнеЗаписейУниверсально #Тогда
    #ДляРегистра("ИдентификаторыОбъектовМетаданных.РегистрНакопленияСвободныеОстатки", "Склад", ", ", ", ")
    #Иначе
    #ПоЗначениям( "РегистрНакопления.СвободныеОстатки","Чтение",",
    "Склады","Склад", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", "," )
    #КонецЕсли

    #Иначе

    Ограничение_отключилось: все идет как надо

    #КонецЕсли
```

Под пользователем с ограниченными правами открыл форму подбора и получил сообщение, какое и ожидал (см. рис.). Делаю вывод, что параметр сеанса отработал как следует.

Сейчас загляну в профайлер, посмотрю, что происходит там.
---
не совсем верно.

Переинициализация происходит в момент написания текста в поиске. Поиск у нас "Стандартный", а не "Расширенный"
---
Да, это я тупой Вас зря мучаю. :) Вероятнее всего поиск осуществляется фоновым заданием, для которого заного инициализируются параметры сеанса. Поэтому-то Ваш параметр и сбрасывается.

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

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

Ну и возможно стоит прислушаться к Сурикату и подумать, почему же запрос выполняется в 10 раз дольше. Мне кажется это нетипичная ситуация, но тут я некомпетентен давать советы.
---
еще раз спасибо за помощь. Я реализовал через константу.

```1c
    Процедура УстановкаПараметровСеанса(ИмяПараметра, УстановленныеПараметры) Экспорт
    //УстановитьПривилегированныйРежим(Истина);
    Если ИмяПараметра = "ЛМ_ОтключениеRLS" Тогда

    ТекстИзКонстанты = Константы.ЛМ_ПользователиКоторымОтключатьRLSНаВремя.Получить();
    Если СтрНайти(ТекстИзКонстанты, " + Строка(ПользователиИнформационнойБазы.ТекущийПользователь()) + ";") = 0 Тогда
    ПараметрыСеанса.ЛМ_ОтключениеRLS = Ложь;
    Иначе
    ПараметрыСеанса.ЛМ_ОтключениеRLS = Истина;
    КонецЕсли;
    УстановленныеПараметры.Добавить("ЛМ_ОтключениеRLS");
    КонецЕсли;

    КонецПроцедуры
```

На форме:

```1c
    &НаСервере
    Процедура ЛМ_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)

    УстановитьПривилегированныйРежим(Истина);
    Константы.ЛМ_ПользователиКоторымОтключатьRLSНаВремя.Установить(" + Строка(ПользователиИнформационнойБазы.ТекущийПользователь()) + ";");
    УстановитьПривилегированныйРежим(Ложь);

    КонецПроцедуры

    &НаСервере
    Процедура ЛМ_ПриЗакрытииПослеНаСервере()

    УстановитьПривилегированныйРежим(Истина);
    ТекстИзКонстанты = Константы.ЛМ_ПользователиКоторымОтключатьRLSНаВремя.Получить();
    ТекстИзКонстанты = СтрЗаменить(ТекстИзКонстанты, " + Строка(ПользователиИнформационнойБазы.ТекущийПользователь()) + ";", ");
    Константы.ЛМ_ПользователиКоторымОтключатьRLSНаВремя.Установить(ТекстИзКонстанты);
    УстановитьПривилегированныйРежим(Ложь);

    КонецПроцедуры
```

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

По поводу Суриката, таблица "Номенклатуры" у нас достаточно большая (более 50к записей) так же происходит левое соединение с двумя таблицами ограничений, поэтому выполняется в 10 раз дольше. Чтобы этого не было, мы пытаемся минимизировать обращений запроса.
---
Позволю себе сделать замечание. :)

При установке константы во время создания формы Вы затираете ранее записанных пользователей.
---
Упс... точно=) спасибо, сейчас изменю=)
---
Ну и предлагаю тогда использовать не представление пользователя, а его уникальный идентификатор для пущей надежности.
---
Уточните, пожалуйста, а с какой именно формой Вы работаете?
---
А на плане запроса запрос к таблице в EXISTS занимает длительное время?

А что за параметр "&ОграничениеДоступаНаУровнеЗаписейУниверсально"? В последних типовых на старом RLS шаблон только ПоЗначениям
---
да, достаточно длительно, в пятницу замеряли в профайлере, там разница была почти в 10 раз...

"А что за параметр "&ОграничениеДоступаНаУровнеЗаписейУниверсально"? В последних типовых на старом RLS шаблон только ПоЗначениям"

данный параметр это тоже ПараметрСеанса, который получает с константы установлен ли RLS или нет.
---
достаточно длительно, в пятницу замеряли в профайлере, там разница была почти в 10 раз...

"А что за параметр "&ОграничениеДоступа
Т.е. это ваш собственный RLS?

Не, я не об этом. Судя по всему у вас MS SQL и вы можете посмотреть план запроса и определить почему есть разница.
---
dhurricane спасибо, большое за помощь!
---
Такая тема и такое странное решение...
И какой профит в итоге? Как изменился поиск? Сколько номенклатуры?
Что-то не верится, что из-за какого-то rls с видом доступа по складам прям лаги наблюдаются.
---
Искал решение своей проблемы и набрел на эту тему. Мало ли вдруг кто-то другой прочитает.

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

Решил довольно просто - убрал инициализацию параметра при запуске программы. Теперь параметр инициализируется только при открытии формы и больше не слетает.