Всем привет.
Не могу проверить нормально производительность запроса. Стало интересно какой запрос 1С (8.3.22) быстрее отработает на MS SQL на больших размерах таблиц (свыше миллиона записей в каждой таблице)? Либо они одинакого отработают по времени (запросы ниже).
Вариант-1:
Временная таблица с отбором по ссылке. Потом соединение с временной таблицей.
ВЫБРАТЬ
Т1.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ
ИЗ
Документ.КакойТоДокументМиллионЗаписей КАК Т1
ГДЕ
Т1.Ссылка = &Ссылка ;
ВЫБРАТЬ
Т1.Ссылка КАК Ссылка
ИЗ
ВТ КАК Т1
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КакойТоРегистрМиллоинЗаписей КАК Т2
ПО Т1.Ссылка = Т2.СсылкаНаДокумент
Показать
Вариант-2:
Соединение двух таблиц, потом отбор по ссылке.
ВЫБРАТЬ
Т1.Ссылка КАК Ссылка
ИЗ
Документ.КакойТоДокументМиллионЗаписей КАК Т1
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КакойТоРегистрМиллоинЗаписей КАК Т2
ПО Т1.Ссылка = Т2.СсылкаНаДокумент
ГДЕ
Т1.Ссылка = &Ссылка
Известно, что MS SQL сначала выполняет конструкцию "ИЗ", потом "СОЕДИНЕНИЕ", потом "ГДЕ" и т.д.
Будет ли план запроса в Варианте-2 сначала соединять все записи обеих таблиц между собой, а потом накладывать отбор?
У меня время выполнения запроса почти одинаковое время показывает на реальных данных (десятки секунд) для обоих вариантов.
У регистра не индексируемое поле.
Комментарий. Сначала выполняется Соединение таблиц. Об этом написано в учебниках SQL. Поэтому перед соединением необходимо тщательно подготовить таблицы: убрать «ненужные» записи, подключить индексы. Контрпример на сравнение очередности "Соединение таблиц" - "Проверка условия ГДЕ" пока не придумал.
(13) Там фильтр в ГДЕ относится к первой таблице. Так что в любом случае в современных реалиях первая таблица будет отобрана по фильтру до соединения, раз фильтр - это уникальный индекс (не может быть две одинаковые ссылки в одной таблице). Она и будет потом искаться в таблице второй.
Вы сами ответили на свой вопрос. Очевидно, что ms sql сначала прикидывает, что эффективнее сделать: соединение или отбор, ведь отбор для основой таблицы при левом соединении равносилен условию в соединении.
В первом случае тратится время на создание ВТ, во втором - время на "прикидывание".
12.
spacecraft
19.02.25 20:11 Сейчас в теме+0.1 $m
(1) второй вариант.
Оптимизатор отработает правильно.
Приблизительно такой план выполнения запроса получится:
Fields:(
T1._IDRRef,
T2._Fld31105,
T2._Fld31106
)
_REFERENCE188 (T1) RANGE SCAN USING INDEX (_REFERENCE188_S_HPK@) (2 fields)
WHERE
(T1._IDRRef = 80290015E9B8C48D11E2CDED714AB055)
NESTED OUTER LOOP
_INFORG31103 (T2) RANGE SCAN USING INDEX (_INFORG31103_1@) (4 fields)
WHERE
(08 = T2._Fld31104_TYPE)
AND
(000000BC = T2._Fld31104_RTRef)
AND
(T1._IDRRef = T2._Fld31104_RRRef)
Какую задачу решаем? Простую - прочитать данные из таблиц, т.е. из файла, из страниц в этом файле. Чем меньше прочитаем - тем лучше. В обоих случаях читаем одно и то же, если не затупит оптимизатор.
Отсюда очевидно, что читать надо соединяемые таблицы минимально, по индексам.
Отсюда очевидно, что в первом случае мы читаем одну строчку таблицы и кладем ее во временную таблицу, потом читаем все строчки из второй таблицы, которые соответствуют условию связи. Если у нас есть индекс на эту связь, то мы читаем оттуда только индекс, а по нему уже только те строчки, которые равны. Если индекса нет, то мы читаем все строчки второй таблицы, а дальше оставляем только те, которые соответсвуют условию.
Во втором случае мы читаем ту же одну строчку из первой таблицы и те же строчки из второй. И тоже все упирается в индекс.
Т.е. в конкретно этом случае нет вот вообще никакой разницы, ну кроме того, что в первом случае ты больше пишешь слов.
ЗЫ: вообще, тут очевидно, что лучше вообще первую таблицу не читать: "выбрать чтото из регистр где документссылка = &ссылка"
(7) Нужны же записи из РС. Их может быть много или не быть. Понятно, что третий вариант при отсутствии записей в РС даст другой результат, но думаю это не сильно принципиально...
(6) если в регистре нет этого документа, то запрос вернется пустой. Пример на сайте курсы-рф:
курсы-по-1с. рф/бесплатное/2019-12-24-about-the-difference-in-conditions-in-the-join-tables
P.S. почему-то ссылка нормально не копируется с доменом .рф
(15) Если временная таблица будет занимать места в несколько гигов, то быстрее точно не будет. И память кончится быстро. :-)
SQL ещё и статистику использует, сначала один план запроса выполняется, а со временем на тех же данных запрос может выполняться уже иначе. Хотя данные могли сильно не меняться.