Первая таблица большая очень. 13 млн
Из неё поле (без индекса, одно из) соединяем со второй таблицей "маленькой" 100 тыс.записей
Во второй таблице поле соединения проиндексировано.
У меня не ВНУТРЕЕНЕЕ СОЕДИНЕНИЕ, а Левое соединение.
Нужно ли добавлять индекс на поле соединения первой таблицы?
Нужно ли добавлять индекс на поле соединения первой таблицы?
В моем представлении в этом случае база будет брать строку из 1-ой таблицы и искать во второй.
Следовательно индекс в первой таблице не нужен, во всяком случае, если вы не пытаетесь использовать это поле первой таблицы где-то еще, например, в условии ГДЕ, или сортировке.
Нужен ли индекс во-второй зависит от его селективности, а также является ли проиндексированное поле ведущем в индексе.
By the way, если речь идет о физической таблице, то она итак в 1С (всегда?) имеет кластерный индекс.
(1) нужно. Если левая таблица по определению больше правой, то скорее всего оптимизатор будет соединять правую таблицу с левой внутренним соединением и добавит недостающие записи из левой.
Т.е. именно к меньшей таблице будет произведено соединение большей таблицы. Соответственно индекс в большей как правило настоятельно рекомендуется.
а что за большая таблица? очень на регистр сведений похоже
так в нем измерения изначально как-то индексированы
как в документах и справочниках некоторые поля. ссылка, Дата, Код....)
(4)
Большая таблица - это регистр сведений, а поле соединения это измерение, не первое и не второе
по счету, где-то внизу...
Указывать индексировать у этого измерения или нет? (поменять порядок измерений нельзя)
Ну а как делается соединение? Есть несколько способов у скула.
1. Выбрать все строки первой таблицы и найти для каждой из них строку во второй таблице.
1.0. нужно понимать, что если в исходной таблице у нас 13кк записей, то все эти строки будут выбраны, отсюда:
1.0.1. Если во второй таблице есть индекс, то для каждой строки второй таблицы будет произведено log 2(N) "чтений". В действительности, мы прочитаем индекс фактически весь и сразу, т.к. на все 13кк первой таблицы должна найтись строка во второй. Это называется NESTED LOOP. Но по индексу. Т.е. это быстрый поиск в цикле.
1.0.2. Если во второй таблице индекса нет, то мы можем попробовать соединить строки методом HASH JOIN. Для этого скул строит по соединяемым колонкам unorderedmap - соответствие. В идеальном случае в нем поиск отрабатывает за O(1), т.е. "сразу". Но идеальные случаи часто бывают в сказках, а в реальной жизни происходят коллизии, когда два и более значения оказываются с одинаковым HASH. Чем больше значений в списке, тем больше коллизий.
Т.е. у нас по первой таблице производится построение unorderedmap - 13кк значений. Потом по второй таблице строится unorderedmap, потом уже для всех значений первой таблицы ищутся все значения второй. Ну тут от значений все зависит прямо.
1.0.3. Если в обоих таблицах есть индекс, то это однопроходной скан индекса. M + N.
1.1. У нас может быть наложен еще какой-то отбор на поля первой таблицы, чтобы не выбирать все 13кк значений.
1.1.1. Есть индекс на фильтр?
1.1.2. Нет индекса на фильтр?
...
Индекс - это упорядоченный по полям массив, в котором эти поля дополнительно лежат. Типа ["А","Б","В",...]. По индексу можно хорошо соединяться. Если в обоих таблица есть индекс, то соединение происходит за M + N чтений. Если только во второй таблице, то M * Log 2(N). HASH JOIN требует построения массива для двух таблиц, а это уже больше M + N, т.к. расчет хеш-функции не является бесплатным, плюс коллизии.
(8) Шансы того, что скл сервер выберет nested loop при джойне 13kk записей, весьма малы. Разве что там TOP будет в запросе или это подзапрос в EXISTS, например. Скорее всего просто построит хэши по меньшей таблице и прогонит через них большую. В постгресе, подозреваю, примерно так же будет, но голову на отсечение не дам
Шансы того, что скл сервер выберет nested loop при джойне 13kk записей
Там смотрятся две таблицы. 13кк + 100к в любом случае уже есть, если нет доп.фильтров, попадающих в индекс. И log 2(100к) = 16,3 где-то, т.е. 13кк х 16,3к : 2 -> эффективность NESTED LOOP. Для 13кк хеш-таблицу строить скул вполне может выбрать, но он строит ее по меньшей таблице. И если у нас поля соединения - это уникальные поля (ссылка, например), то будет много сбрасываний на диск при построении хеша большой таблицы. По крайней мере так пишет кто-то где-то. Остается понять, что для скула в данном случае маленькая таблица, что средняя и что большая.
13кк + 100к в любом случае уже есть, если нет доп.фильтров, попадающих в индекс. И log 2(100к) = 16,3 где-то, т.е. 13кк х 16,3к : 2 -> эффективность NESTED LOOP.
В пятничный вечер я уже не особо могу в эти расчёты вникнуть, но точно знаю, что оптимизатор считать будет совсем не так. И при таких вводных данных для сферического левого джойна в вакууме без дополнительных условий вероятность увидеть nested loop стремится к нулю. При индексе на соотв. поле на таблице 13кк возможен еще вариант мердж-джойном.