Имя: Пароль:
1C
1С v8
Как можно ускорить проверку на есть null при левом соединении?
0 kortun
 
20.08.19
10:39
Добрый день.

Есть запрос вида

ВЫБРАТЬ
    Контрагенты.Наименование КАК Наименование,
    Контрагенты.Ссылка КАК Ссылка
ИЗ
    Справочник.Контрагенты КАК Контрагенты
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РеквизитыКонтрагентов КАК РеквизитыКонтрагентов
        ПО Контрагенты.Ссылка = РеквизитыКонтрагентов.Ссылка
ГДЕ
    РеквизитыКонтрагентов.Ссылка ЕСТЬ NULL

Записей в справочнике 32 млн, в регистре сведений 65 млн.

Время выполнения такого запроса 3 минуты, в результате 60 записей примерно, можно как то ускорить такой запрос?

Необходимо получить контрагентов, у которых отсутствуют записи в регистре сведений. Поля связи все проиндексированы.
1 Cyberhawk
 
20.08.19
10:46
"получить контрагентов, у которых отсутствуют записи в регистре сведений" //
Влоб не предлагать? Запрос к таблице регистра с выбором тамошних ссылок и этот фильтр на условие к таблице контрагентов
2 Fragster
 
гуру
20.08.19
10:50
добавить в справочник индексируемое поле "ЕстьРеквизиты" и отбирать по нему
3 kortun
 
20.08.19
10:52
(2) такое сложно организовать, данные в справочник контрагенты попадаю разными способами, в том числе прямой записью в скуль, подписки не работают в этом случае, доработать все пути создания много времени займет
4 kortun
 
20.08.19
10:53
(1) не совсем понятно, как применить фильтр к таблице? можно набросок запроса?
5 Fragster
 
гуру
20.08.19
10:54
(3) >в том числе прямой записью в скуль
ну сами себе расставили грабли - сами и терпите. Без денормализации в любом случае будет скан, причем обеих таблиц.
6 Fragster
 
гуру
20.08.19
10:55
можно сделать отдельный РС "КонтрагентыБезРеквизитов", будет даже эффективнее, чем (2)
7 Said_We
 
20.08.19
10:56
(0) "Записей в справочнике Контрагенты 32 млн" - "центральная" налоговая или ПФР что ли? Откуда столько контрагентов взяли?
8 Said_We
 
20.08.19
10:59
150 млн население страны. 32 млн контрагентов у (0).
Это получается примерно по 1 контрагенту на каждые пять человек, включая младенцев и стариков.
Может это не контрагенты все-таки?
9 aleks_default
 
20.08.19
11:02
(8)У них филиал транснациональной корпорации, что ты понимаешь :)
10 kortun
 
20.08.19
11:02
(6) а как его заполнять? сначала же также надо найти их
11 kortun
 
20.08.19
11:03
(7) есть дубли контрагентов, с ними боремся, но борьба продвигается не быстро
12 xXeNoNx
 
20.08.19
11:03
а скока показывает
ВЫБРАТЬ РАЗЛИЧНЫЕ
Ссылка
ИЗ
РегистрСведений.РеквизитыКонтрагентов

?
13 aleks_default
 
20.08.19
11:04
(9)Правда работают только с 60-ю
14 RomaH
 
naïve
20.08.19
11:05
(12) явно 32 000 000 - 60
15 RomaH
 
naïve
20.08.19
11:06
(10) повесить фоновое раз в 600 сек
16 kortun
 
20.08.19
11:07
(10) фоновое уже висит, много ресурсов отнимает, ищу способы уменьшить
17 Cyberhawk
 
20.08.19
11:07
(4) "где"
18 Said_We
 
20.08.19
11:08
(11) Дубли!!!! Да у вас фабрика клонов - фирм однодневок. На каждый день новую по ходу заводите. Как фирмы прокладки.
Причину появления двойников устранили?
19 kuzyara
 
20.08.19
11:12
https://crate.io/a/sql-subquery-vs-left-join/

вот например люди ускорили LEFT JOIN / IS NUL в 260 раз ))
20 xXeNoNx
 
20.08.19
11:12
(18) видел я одну конфу еще на клюшках.., там спр номенклатура сделали подчинение спр Организации...
21 kortun
 
20.08.19
11:12
(18) причину устраняем, но процесс не быстрый, а болит уже сейчас
не об этом речь, в каком направление двигаться и так понятно и работы ведутся.

хотел бы пока ускорить временное решение
22 Said_We
 
20.08.19
11:13
ВЫБРАТЬ
    Контрагенты.Наименование КАК Наименование,
    Контрагенты.Ссылка КАК Ссылка
ИЗ
    Справочник.Контрагенты КАК Контрагенты
        ЛЕВОЕ СОЕДИНЕНИЕ
        (ВЫБРАТЬ
                РеквизитыКонтрагентов.Ссылка КАК Ссылка
        ИЗ РегистрСведений.РеквизитыКонтрагентов КАК РеквизитыКонтрагентов
        СГРУППИРОВАТЬ ПО
                РеквизитыКонтрагентов.Ссылка) КАК РеквизитыКонтрагентов  
        ПО Контрагенты.Ссылка = РеквизитыКонтрагентов.Ссылка
ГДЕ
    РеквизитыКонтрагентов.Ссылка ЕСТЬ NULL

***************
ВЫБРАТЬ
    Контрагенты.Наименование КАК Наименование,
    Контрагенты.Ссылка КАК Ссылка
ИЗ
    Справочник.Контрагенты КАК Контрагенты
ГДЕ
    НЕ РеквизитыКонтрагентов.Ссылка В
        (ВЫБРАТЬ
                РеквизитыКонтрагентов.Ссылка КАК Ссылка
        ИЗ РегистрСведений.РеквизитыКонтрагентов КАК РеквизитыКонтрагентов
        СГРУППИРОВАТЬ ПО
                РеквизитыКонтрагентов.Ссылка)
23 Said_We
 
20.08.19
11:15
(21) Расскажи всем какой быстрее. Только запусти по раза два хотя бы каждый.
24 aleks_default
 
20.08.19
11:16
(22) Ты попал мужик
25 ptiz
 
20.08.19
11:16
(21) У старых контрагентов реквизиты заполняются? Может сделать проверку только для "новых"? Скажем, последние 10% кодов.
26 kuzyara
 
20.08.19
11:17
27 Said_We
 
20.08.19
11:18
(26) Тссс!!!!
28 xXeNoNx
 
20.08.19
11:20
(22) Фу
29 ПускинАС
 
20.08.19
11:23
(0) ну для начала я бы не выбирал наименование на этом шаге, поигрался бы с индексированием .
30 Said_We
 
20.08.19
11:26
(28) Подожди ФУ. :-)
Ща (0) расскажет, а зачем он этот запрос вообще хочет.
31 Said_We
 
20.08.19
11:27
Сегодня не пятница? Нет?
Странно.
32 kortun
 
20.08.19
11:30
(22) первый запрос 80 секунд, второй 120, но уже быстрее простого левого соединения, спасибо за пример.

сейчас еще план запроса посмотрю
33 Fragster
 
гуру
20.08.19
11:36
еще можно

ВЫБРАТЬ
    Контрагенты.Наименование КАК Наименование,
    Контрагенты.Ссылка КАК Ссылка
ИЗ
    Справочник.Контрагенты КАК Контрагенты
Где не 1 в (ЫБРАТЬ первые 1
                1
        ИЗ РегистрСведений.РеквизитыКонтрагентов КАК РеквизитыКонтрагентов где РеквизитыКонтрагентов.Ссылка = Контрагенты.Ссылка)
34 Said_We
 
20.08.19
11:39
А так может и дольше, так как ВТ большая может быть...

ВЫБРАТЬ
   РеквизитыКонтрагентов.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_РеквизитыКонтрагентов
ИЗ РегистрСведений.РеквизитыКонтрагентов КАК РеквизитыКонтрагентов
СГРУППИРОВАТЬ ПО
   РеквизитыКонтрагентов.Ссылка
ИНДЕКСИРОВАТЬ ПО
   РеквизитыКонтрагентов.Ссылка
;

ВЫБРАТЬ
    Контрагенты.Наименование КАК Наименование,
    Контрагенты.Ссылка КАК Ссылка
ИЗ
    Справочник.Контрагенты КАК Контрагенты
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_РеквизитыКонтрагентов КАК РеквизитыКонтрагентов  
        ПО Контрагенты.Ссылка = РеквизитыКонтрагентов.Ссылка
ГДЕ
    РеквизитыКонтрагентов.Ссылка ЕСТЬ NULL

****************************
По аналогии (33)

ВЫБРАТЬ
   РеквизитыКонтрагентов.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_РеквизитыКонтрагентов
ИЗ РегистрСведений.РеквизитыКонтрагентов КАК РеквизитыКонтрагентов
СГРУППИРОВАТЬ ПО
   РеквизитыКонтрагентов.Ссылка
ИНДЕКСИРОВАТЬ ПО
   РеквизитыКонтрагентов.Ссылка
;

ВЫБРАТЬ
    Контрагенты.Наименование КАК Наименование,
    Контрагенты.Ссылка КАК Ссылка
ИЗ
    Справочник.Контрагенты КАК Контрагенты
Где не 1 в (ВЫБРАТЬ первые 1
                1
        ИЗ ВТ_РеквизитыКонтрагентов КАК РеквизитыКонтрагентов где РеквизитыКонтрагентов.Ссылка = Контрагенты.Ссылка)
35 DrWatson
 
20.08.19
11:40
(33) 32 мильёна запросов к регистру?
36 Said_We
 
20.08.19
11:45
(35) Там по одной записи, первой попавшейся.
37 Said_We
 
20.08.19
11:48
(32) Так что там с производительностью? Еще "три" варианта скинули :-)
38 НЕА123
 
20.08.19
11:49
зачем поле Наименование?
39 Said_We
 
20.08.19
11:51
(38) В (0) было. По мне так оно не нужно.
40 DrWatson
 
20.08.19
11:51
(36) Просто всегда полагал, что большое количество запросов, даже по одной записи будет долго.
Интересно посмотреть что будет у автора на практике.
41 Said_We
 
20.08.19
11:54
(40) На самом деле не долго, но на 32 миллионах записях интересно посмотреть.... :-)
42 Botanik8888
 
20.08.19
11:56
43 Said_We
 
20.08.19
12:00
(42) Там (33) модератор :-)
44 Said_We
 
20.08.19
12:03
(0), (32) Каков результат-то? Обед что ли?
45 kortun
 
20.08.19
12:06
коллеги не волнуйтесь, я тут еще, обновляется статистика, сейчас закончится, продолжу тесты.
:) спасибо за участие
46 powunexaxe
 
20.08.19
12:08
(45) никто не волнуется, всем пофиг))
47 aleks_default
 
20.08.19
12:19
Я волнуюсь
48 Fragster
 
гуру
20.08.19
12:41
(43) я и тут модератор. а где 1 в (выбрать первые 1 1 ) преобразуется в exists
49 Said_We
 
20.08.19
12:53
(48) А такой запрос преобразуется в exists?
где А.А1 в (выбрать первые 1 В.А1 ИЗ ....)
50 Конструктор1С
 
20.08.19
12:55
(0) Записей в справочнике 32 млн, в регистре сведений 65 млн. ... Поля связи все проиндексированы.

А толку от индексов, если лопатить целиком две таблицы?
51 Вафель
 
20.08.19
12:58
(50) чтобы мердж делать
52 Tonik992
 
20.08.19
13:01
А вам точно наименование нужно? Уберите его из запроса.
53 ProxyInspector
 
20.08.19
13:07
(26) https://crate.io/a/sql-subquery-vs-left-join/
    там вполне рабочий способ. Должен Ускорить запрос раз в 1000
    что-то так
    
ВЫБРАТЬ
    СправочникКонтрагенты.Ссылка
ИЗ
    Справочник.Контрагенты КАК СправочникКонтрагенты
ГДЕ
    СправочникКонтрагенты.Ссылка НЕ В (ВЫБРАТЬ Владелец ИЗ РегистрСведений.ПериодическиеРеквизитыКонтрагент)
54 Tonik992
 
20.08.19
13:09
(53) Там используется оператор IN, но никак не NOT IN.
Не годится.
55 Вафель
 
20.08.19
13:10
(53) думаешь у всех дб одинаковые косяки?
56 ProxyInspector
 
20.08.19
13:14
Я думаю не важно.
  Суть такая, что когда делаешь левое соединение, то анализируется таблица в 60 млн записей на is null
  А когда Ссылка НЕ В () там используются индексы
  У меня нет под рукой базы с большим количеством записей
57 Конструктор1С
 
20.08.19
13:26
(51) кстати, насчет мерге... Нужно переписать запрос как-то так, и должно быть щастье:

ВЫБРАТЬ
    Контрагенты.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_Ссылки
ИЗ
    Справочник.Контрагенты КАК Контрагенты
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.РеквизитыКонтрагентов КАК РеквизитыКонтрагентов
        ПО Контрагенты.Ссылка = РеквизитыКонтрагентов.Ссылка
ГДЕ
    РеквизитыКонтрагентов.Ссылка ЕСТЬ NULL

;

ВЫБРАТЬ
    Контрагенты.Ссылка КАК Ссылка,
    Контрагенты.Код КАК Код,
    Контрагенты.Наименование КАК Наименование,
    Контрагенты.ИНН КАК ИНН
ИЗ
    Справочник.Контрагенты КАК Контрагенты
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Ссылки КАК ВТ_Ссылки
        ПО Контрагенты.Ссылка = ВТ_Ссылки.Ссылка

Это если РеквизитыКонтрагентов.Ссылка - первое измерение в РС
58 Конструктор1С
 
20.08.19
13:29
+ если есть уверенность, что в выборку должно попасть немного записей. Если будут миллионы, то накладные расходы на создание временной таблицы сожрут всю эффективность
59 sitex
 
naïve
20.08.19
13:30
(0)
Может это сделать на sql , все равно как вы же сами пишите запись у вас идет и напрямую.
60 ProxyInspector
 
20.08.19
13:34
Известно, что итоговых записей будет мало
61 H A D G E H O G s
 
20.08.19
13:34
Измерение
РеквизитыКонтрагентов.Ссылка

на первом месте?

Регистр не периодический?
62 H A D G E H O G s
 
20.08.19
13:37
(57) Думаешь, наименование портит merge из за того, что используется некластерный индекс по наименованию?
63 rsv
 
20.08.19
13:37
(0) первые 100 как вариант
64 Сияющий в темноте
 
20.08.19
13:38
А если выбрать одну таблицу во временную с +1,а потом обьединить с другой но -1 и сгруппировать?
65 H A D G E H O G s
 
20.08.19
13:38
Вообще забавно.
Я бы повтыкал в профайлер.
Автор, дашь базу или доступ?
Я ниче не сломаю.
66 sitex
 
naïve
20.08.19
13:40
(65) Особенно базу ))), чего сразу не написал выложи куда нить .
67 H A D G E H O G s
 
20.08.19
13:41
(66) ftp-шник, гугл диск, нуачо. SQL жмет базы только в путь
68 Конструктор1С
 
20.08.19
14:10
(62) ага
69 Said_We
 
20.08.19
14:36
(58) в (34) сразу написал, что может быть медленнее, если большая таблица в ПОМЕСТИТЬ. Но тут смотреть надо. От данных зависит.
Что за конфигурация не написано. Может каждый реквизит отдельной записью РС храниться. Даже не может, а скорее всего так и есть...

Вопрос как (0) собирается базу от двойников чистить. Если реквизитов нет, то удалить? А если есть....
(63) Правильно написал. Найди одинаковых. Пометь основного. Посмотри на реквизиты. Далее замена ссылок и удаление. Если РБД, то ещё веселее - надо обмены смотреть.
70 kortun
 
20.08.19
15:26
провел еще тесты
(33) заняло по времени 115 секунда
(34) первый запрос 215, второй 138, записей много, логично что дольше стало
71 kortun
 
20.08.19
15:30
(52) похоже на (22) вторую часть, проверю сейчас немного по другому, но думаю так же будет примерно 120 секунд
72 kortun
 
20.08.19
15:31
(61) измерение было второе, сделал первым, результат остались примерно такими же
73 Конструктор1С
 
20.08.19
15:32
(72) регистр периодический?
74 kortun
 
20.08.19
15:32
(66) базу не могу к сожалению, 3 терабайта и безопасники не разрешат :(
75 kortun
 
20.08.19
15:32
(72) независимый, забыл отписать, индекс кластерный и там и там
76 kortun
 
20.08.19
15:34
(69) как двойники чистить уже проработали, с этим нет сложностей, просто на это надо время, база филиальная, путей созданий контрагентов много, выше отписывался, порядок наводим потихоньку
77 sitex
 
naïve
20.08.19
15:53
(70) Замеры запросом напрямую SQL делали ?
78 H A D G E H O G s
 
20.08.19
16:03
Тогда ставлю на mdop<>1
79 Вафель
 
20.08.19
16:03
самый простой сейчас способ ускориться  - вынести таблицы на отдельные диски
80 Вафель
 
20.08.19
16:04
(78) в данном случае мдоп > 1 таки как раз может ускорить
81 H A D G E H O G s
 
20.08.19
16:07
(75) Собери план запроса, действительный и в xml. Только так можно победить
82 Вафель
 
20.08.19
16:09
(81) а что там собирать: 2 скана и мердж
83 Пузан
 
20.08.19
16:12
3 минуты для такого объема данных это много? Как часто запускается запрос?
84 H A D G E H O G s
 
20.08.19
16:14
(82) Это делается за десяток секунд.
85 Пузан
 
20.08.19
16:17
А так, по существу, можно запустить параллельно несколько обработок с неким фильтром.
86 тарам пам пам
 
20.08.19
16:20
Я ни разу не эксперт, но мысль такая пришла - скан кластерного индекса по сути есть скан всей таблицы. А если сделать отдельный некластерный индекс по ссылке? Он же будет сравнительно небольшим по объему и должен гораздо быстрее сканироваться.

Или же выбор колонки из индексированного поля кластерного индекса не будет приводить к чтению всей таблицы? Подскажите, знатоки MS SQL?
87 H A D G E H O G s
 
20.08.19
16:24
(86) Идем на партнерку и просим 1С сделать кастомные индексы
88 тарам пам пам
 
20.08.19
16:27
(87) Ну раз они уже нарушают и создают контрагентов прямой записью в SQL (и огребают сейчас проблем из-за этого), то добавить кастомный индекс не должно быть проблемой. Ну и эксперимента ради - хотя бы для проверки теории.
89 kortun
 
20.08.19
16:33
(86) некластерный уже пробовал, прироста можно сказать нет, есть погрешности в +- 5 секунд при выполнении запросов, но это от нагрузки зависит
90 kortun
 
20.08.19
16:34
(81) план запроса скан и мердж, и с кластерными индексами и с некластерными, одинаковый
91 H A D G E H O G s
 
20.08.19
16:34
Так. У меня подобное соединение справочника на 4млн и РС на 2.8 млн занимает 2.7 секунды на прогретом кеше.
92 H A D G E H O G s
 
20.08.19
16:35
У меня 2 некластерных скана и hashjoin
93 kortun
 
20.08.19
16:36
(78) с mdop пока поиграться не дает dba админ, попробую в выходные
94 pavig
 
20.08.19
16:37
(8)
Контрагенты и физлица это как бы совсем не одно и то же
95 Cyberhawk
 
20.08.19
16:37
(86) Что-то ты до кластерного докапываешься. По нему ведь не только скан бывает.
96 eTmy
 
20.08.19
16:39
А автор случаем проверяет не в консоли запросов? Вдруг у него там стоит выводить 100000 записей и основное время тратится на вывод строк?
97 kortun
 
20.08.19
16:41
(96) в консоле, но в результат выводится 60 записей
98 Tonik992
 
20.08.19
16:50
(91) супер компьюче у вас
99 H A D G E H O G s
 
20.08.19
16:53
Ну на самом деле у меня новые вопросы к SQL
100 Fragster
 
гуру
20.08.19
16:54
(98) так 4 мегазаписи гуидов это всего-то в районе ста мегабайт табличка
101 H A D G E H O G s
 
20.08.19
16:55
Как так то?
http://prntscr.com/ov5387

Зачем здесь индекс _Reference51_ByPredefinedIDNotUniq, если в нем нет поля _IDRRef ?

Или SQL неявно обращается к данным и на плане запроса это не показывает?
102 H A D G E H O G s
 
20.08.19
16:56
Вот текст запроса
SELECT
T1._IDRRef,
T2._Fld27656
FROM dbo._Reference51 T1
LEFT OUTER JOIN dbo._InfoRg27654 T2
ON ((T2._Fld27655RRef = T1._IDRRef)) AND (T2._Fld931 = P1)
WHERE ((T1._Fld931 = @P2)) AND (T2._Fld27655RRef IS NULL)
103 kortun
 
20.08.19
16:56
(92) у меня тоже hashjoin, если убрать наименование из запроса, по времени 170 секунд заняло
104 H A D G E H O G s
 
20.08.19
16:57
(103) Ты скриншот плана запроса покажи, как я в (101)
105 H A D G E H O G s
 
20.08.19
16:57
(101) Или я что-то не знаю про HashJoin ?
106 Fragster
 
гуру
20.08.19
17:00
(101) а WHERE ((T1._Fld931 = @P2)) что?
107 H A D G E H O G s
 
20.08.19
17:01
(106) ОбластьДанных. Живите теперь с этим.
108 H A D G E H O G s
 
20.08.19
17:01
(107) Купила баба порося.
109 Fragster
 
гуру
20.08.19
17:02
(107) а, это... я помню, жестко выпиливал как-то раз это разделение к херам. не нужно оно в 90% случаев, однако пихают во все тповые.ю оставили бы в корп версиях только - всем бы жилось легче
110 H A D G E H O G s
 
20.08.19
17:04
(109) Как ты его выпилишь? Оно же - памятник.
111 kortun
 
20.08.19
17:05
112 Fragster
 
гуру
20.08.19
17:05
(110) сначала напильником, потом шкуркой, потом мягкой тряпочкй
113 Fragster
 
гуру
20.08.19
17:06
но это гомункул был, созданный из демо базы БСП, а не типовая
114 H A D G E H O G s
 
20.08.19
17:08
(111) В регистре сведений в измерении сидит еще кто-то кроме этого справочника?
115 kortun
 
20.08.19
17:15
(114) нет, только один справочник контрагенты
116 H A D G E H O G s
 
20.08.19
17:17
(115) А, все, вижу, в РС больше записей чем в справочнике. Поэтому хэш для справочника делается.
117 H A D G E H O G s
 
20.08.19
17:18
(115) Ну, попробуйте воткнуть индекс в справочник по полю _IDREF
118 kortun
 
20.08.19
17:44
(117) результаты примерно такие же по времени.
Коллеги всем спасибо за помощь, пока выбрали вариант из (22), ускорение хоть и небольшое, всего в 2 раза, но хоть что-то
Требовать и эффективности, и гибкости от одной и той же программы — все равно, что искать очаровательную и скромную жену... по-видимому, нам следует остановиться на чем-то одном из двух. Фредерик Брукс-младший