|
Секционирование регистра накопления | ☑ | ||
---|---|---|---|---|
0
VitShvets
28.05.18
✎
15:04
|
А баловался ли кто-нибудь? Есть регистр накопления, остатки. Секционировал по «_Period» таблицу итогов, по годам. Когда пишу 1Совый запрос:
РегистрНакопления.МойРегистр.Остатки(, [Отбор по одному полю в 50 тысяч строк]) 1С это превращает в: exec sp_executesql('..... .... FROM dbo._AccumRgT27531 T2 WITH(NOLOCK) WHERE T2._Period = P1 .....' P1 datetime2(3).... '5999-11-01 00:00:00' В итоге SQL, из за sp_executesql и не явного указания периодов, не понимает что надо поднимать только одну секцию с периодом '5999-11-01 00:00:00' и поднимает все секции. Хотя если в менеджмент студии переписать запрос на: … FROM dbo._AccumRgT27531 T2 WITH(NOLOCK) WHERE T2._Period = '5999-11-01 00:00:00' …. Всё работает! Разница в скорости колоссальная – 1 секунда против 3 минут. Решение есть - отказаться от запросов 1С против прямых запросов, но уж больно не хочется этого делать. Есть идеи как можно повлиять на РегистрНакопления.МойРегистр.Остатки ? |
|||
96
VitShvets
20.06.18
✎
16:05
|
(90) Я правильно идею понимаю? Делаем регистр оборотным, вешаем агрегаты, добавляем регламентное заполнение регистра сведений как "итогов". В целевом запросе по остаткам собираем "итоги" + обороты за нужный период. Есть где почитать? Но, имхо, проще тогда уж прямые запросы. Не нужно новые сущности плодить, а запрос по сути тот-же самый - "ближние итоги плюс обороты". А в SQL и индекс можно подобрать и вообще...
(91) >> Кто бы мог подумать! Вот не надо тут. Я не сомневался, что пересчет итогов поможет, но ожидал сокращения записей не более чем на несколько десятков процентов. То, что количество записей сократились в разы, и приятное и не приятное открытие. Приятное, что помогло быстро решить локальную задачу. Неприятное, что этим надо следить и следить пристально. Через месяц буду анализировать скорость деградации, видимо писать job'ы/регламенты. (92), (93) Я что-то пропустил? Агрегаты вроде как можно только для оборотного регистра создать? Я использовал, оборотный регистр "Продажи". Отчёты, если в агрегат попадёшь, строятся очень быстро. |
|||
97
Fragster
гуру
20.06.18
✎
16:09
|
кстати, может быть проще выключить итоги по периодам и оставить только текущие итоги?
|
|||
98
VitShvets
20.06.18
✎
16:22
|
(94) Татычё?! Есть такая штука в составе средств управления сиквелом, профайлер называется. Он позволяет, в том числе "ловить" запросы генерируемые непосредственно 1С, вместе с актуальными их планами. Естественно запрос можно взять и нежно "покрутить" уже в SSMS, посмотреть как меняется его план.
(95) А поведай ка мне Антон Долгов, какие-нибудь есть идеи на тему 2-х терабайтной базы на предмет "обрезать", "ускорить" и всего-вот-этого-вот? При условии что монопольного доступа к базе есть 1-2 часа в сутки и сильно не каждый день. Или только овна на вентилятор вбросить не слабо? Не знаю с какого перепуга какой-то там Рупасов кого-то там расстреливал, это всяко не говорит о его выдающихся умственных способностях, во всяком случае в твоём изложении. |
|||
99
Genayo
20.06.18
✎
16:42
|
(96) Таки да, для оборотных агрегаты. Мы об этом и говорим :)
|
|||
100
Genayo
20.06.18
✎
16:45
|
(97) Тогда надо делать 2 базы - одну оперативную, только с текущими итогами, а другую отчетную - наоборот без текущих итогов. Ибо если в базе только с текущими итогами задать период хотябы год - помрет нафик с такими объемами, как у ТС...
|
|||
101
VitShvets
20.06.18
✎
16:55
|
(97) Не, иногда требуется посмотреть сильно прошлый период. Я попробую поиграться урезанием "старых периодов", что 8.3 умеет сама установкой минимального периода итогов. Профайлером посмотрю запросы-зависимости, попробую руками почистить. Но для начала надо понять скорость деградации таблицы итогов, особенно оперативных.
|
|||
102
VitShvets
20.06.18
✎
17:10
|
(99) Так агрегаты ещё с 8.2, если не 8.1 появились. В 8.3 добавили им интеллекта по поводу "рекомендаций" и позволили управлять из предприятия.
(100) Я думал про 2 базы - архивная и оперативная. В оперативной последние 3-6 месяцев, в архивной всё остальное. Народ работает только в оперативной, длинная отчетность формируется в архивной. Не придумал как их создать быстро и как связывать между собой на предмет актуализации архивной. Так чтобы это работало быстро. |
|||
103
Антон Долгов
20.06.18
✎
17:39
|
(98) Что именно тебе надо ускорить?
|
|||
104
Genayo
20.06.18
✎
17:43
|
(102) Объемы в сутки очень большие? РИБ не прокатит?
|
|||
105
romix
20.06.18
✎
18:00
|
(0) Смотрели стандартную обработку Все действия - стандартные обработки - управление итогами - полные возможности?
Полные возможности Режим полных возможностей позволяет получить полный доступ ко всем инструментам работы с итогами (закладка Итоги) и агрегатами (закладка Агрегаты) регистров накопления и регистров бухгалтерии. |
|||
106
VitShvets
20.06.18
✎
18:07
|
(103) Ну как обычно - проведение документов, всякие регламентные операции. Самое тяжелое, типовые 1Совые запросы, на которые я не могу никак повлиять. Это виртуальные таблицы "срез последних" и "остатки".
(104) Очень приличные. На пределе. Если будет какой-то сбой, уже есть шанс не догнать. Особенно в контексте планов роста. РИБ по функционалу меня устраивает полностью. Скорее всего будет гибрид какой-то. Метаданные и лёгкие объекты метаданных ходят РИБом, тяжелые SQL. |
|||
107
Антон Долгов
20.06.18
✎
18:11
|
(106) И какой у тебя самый медленный запрос и какой у него план? Выложи в формате sqlplan
|
|||
108
romix
20.06.18
✎
18:20
|
http://1sprogress.ru/anatomiya-registra-nakopleniya-vnutrennee-ustrojstvo-i-struktura-xraneniya.html
1С хранит текущие актуальные остатки (если поставить галку в настройках!) и хранит помесячно от сих до сих (две даты можно поставить в той же форме настроек (105). Таблицы можно пересчитать. То есть вот это надо посмотреть. Далее надо думать что там лучше по сути - регистр остатков или оборотов, закрывается ли он в 0, или там все время растет таблица остатков со временем. |
|||
109
VitShvets
20.06.18
✎
18:21
|
(107) В (0) написано. Не самый, но один из. План не выложу, но там смотреть нечего. Не интересный - более 50% кластеред индекс сик таблицы итогов в части оперативных итогов. Остальное впополам иннер джоин с времянкой-отбором и "агрегация" хэш матчем. Основное в плане, что кластеред индекс сик партиционирован, количество актуальных секций =14.
|
|||
110
romix
20.06.18
✎
18:22
|
Пересчет таблицы итогов еще нужен ибо http://catalog.mista.ru/public/177171/
|
|||
111
Антон Долгов
20.06.18
✎
18:24
|
(109) без партиционирования запрос какой тормозит и какой у него план? что побудило заняться партиционированием? может надо с этого начинать?
|
|||
112
H A D G E H O G s
20.06.18
✎
18:27
|
(109) Там остаточных предикатов точно нет?
|
|||
113
Антон Долгов
20.06.18
✎
18:30
|
(112) а додумывай сам! хрен тебе а не sqlplan, "там смотреть нечего"
|
|||
114
H A D G E H O G s
20.06.18
✎
18:35
|
Хотяяя.
Я правильно понимаю, что автор вытаскивает ВСЕ оперативные итоги, которых 50 тыс строк? |
|||
115
mistеr
20.06.18
✎
18:35
|
(102) Про схему архивная-оперативная и быструю актуализацию можно забыть. Пока 1С не разрешит использовать возможности скуля по быстрой обработке больших объемов данных средствами 1С. То есть многострочный DML.
|
|||
116
VitShvets
20.06.18
✎
18:48
|
(105), (108) Эта история работает с режима совместимости 8.3.5. У меня 8.2.
(110) Это видел, подчерпнул оттуда пару идей. (111) А разве не очевидно, что побудило? Скорость работы не устраивает. Причём основные тормоза именно в тех местах на, которые я повлиять не могу. Обычные "ВЫБРАТЬ бла-бла из ххх.Остатки". Или "ххх.СрезПоследних". (113) Нельзя выкладывать. СБ и всё такое. |
|||
117
VitShvets
20.06.18
✎
18:55
|
(112) Вот сейчас не уверен, что точно понял о чём ты. Поясни плз, что ты имеешь ввиду, на что посмотреть?
(114) Не все, 50 тысяч из нескольких миллионов. Есть кластерный индекс, в нем первое поле период, второе поле, то что участвует в отборе. |
|||
118
VitShvets
20.06.18
✎
18:57
|
(115) Да я как-то не шибко жажду спрашивать разрешения у 1С... Но мне больше нравится CDC.
|
|||
119
H A D G E H O G s
20.06.18
✎
18:58
|
(117) Отбой тревоги. Остаточный предикат работает только в диапазоне индекса. К твоей проблеме это не может относиться.
|
|||
120
H A D G E H O G s
20.06.18
✎
18:58
|
Сейчас я попытаюсь воспроизвести твои идеи.
|
|||
121
nicxxx
20.06.18
✎
19:00
|
(43) в кластерный может попадать из-за того, что много полей тянутся из таблицы.
Important: SQL Server does not use nonclustered indexes if it estimates that a large number of key or RID lookup operations will be required. (Korotkevitch D. - Pro SQL Server Internals) |
|||
122
mistеr
20.06.18
✎
19:00
|
(118) Не спрашивать разрешения это значит жить без поддержки и в постоянном страхе, что завтра с очередным обновлением платформы все поломается.
Есть еще вариант сделать хранилище в отдельной базе (не 1С), сделать его грамотно и юзать как внешний источник. |
|||
123
H A D G E H O G s
20.06.18
✎
19:05
|
Но вообще, цифры ты приводишь дикие.
Я грешу на непрогретый кэш. Но даже после DROPCLEANBUFFERS у меня цифры минимальны. Без всяких секционирований. |
|||
124
H A D G E H O G s
20.06.18
✎
19:10
|
SELECT count(*)
FROM [IEGAIS_MP].[dbo].[_AccumRgT687] Результат: 8896130 за 49 секунд SELECT * FROM [IEGAIS_MP].[dbo].[_AccumRgT687] where [_Period]= ('59991101 00:00:00.000') and _Fld679RRef=0x810E000D3A22309E11E5EC30EF6782BC После перезапуска ms sql сервер Результат: 50598 строк за 0,6 секунд HDD WD 5400, 2 Тб Подозреваю, что жив кэш HDD |
|||
125
H A D G E H O G s
20.06.18
✎
19:11
|
0,6 секунд вполне укладывается в твою 1 секунду. Но без секционирования.
Что то не так у тебя с запросом от 1С. |
|||
126
H A D G E H O G s
20.06.18
✎
19:11
|
Сейчас сделаю запрос через 1С.
|
|||
127
H A D G E H O G s
20.06.18
✎
19:21
|
Ну как бэ через 1С то совсем другой запрос получается, автор.
С вложенной таблицей и группировочкой разделенных итогов. |
|||
128
H A D G E H O G s
20.06.18
✎
19:38
|
В любом случае, после перезапуска 1С и MS SQL запрос
Запрос=Новый Запрос; Старт=ТекущаяУниверсальнаяДатаВМиллисекундах(); Запрос.Текст= "ВЫБРАТЬ | ТоварыНаСкладахОстатки.Организация, | ТоварыНаСкладахОстатки.ОбособленноеПодразделение, | ТоварыНаСкладахОстатки.Склад, | ТоварыНаСкладахОстатки.Номенклатура, | ТоварыНаСкладахОстатки.Серия, | ТоварыНаСкладахОстатки.КоличествоОстаток |ИЗ | РегистрНакопления.ТоварыНаСкладах.Остатки(, Организация = &Организация) КАК ТоварыНаСкладахОстатки"; Запрос.УстановитьПараметр("Организация",Объект.Организация); Выборка=Запрос.Выполнить().Выбрать(); Стоп=ТекущаяУниверсальнаяДатаВМиллисекундах(); Сообщить(Строка(Выборка.Количество())+" строк за "+Строка(Стоп-Старт)+" мсек."); Выполняется: 42 074 строк за 3 002 мсек. Размер таблицы 8896130 строк В профайлере он же exec sp_executesql N'SELECT T1.Fld679RRef, T1.Fld680RRef, T1.Fld681RRef, T1.Fld682RRef, T1.Fld683RRef, T1.Fld684Balance_ FROM (SELECT T2._Fld679RRef AS Fld679RRef, T2._Fld680RRef AS Fld680RRef, T2._Fld681RRef AS Fld681RRef, T2._Fld682RRef AS Fld682RRef, T2._Fld683RRef AS Fld683RRef, CAST(SUM(T2._Fld684) AS NUMERIC(22, 2)) AS Fld684Balance_ FROM dbo._AccumRgT687 T2 WHERE T2._Period = P1 AND ((T2._Fld679RRef = @P2)) AND (T2._Fld684 <> @P3) AND (T2._Fld684 <> @P4) GROUP BY T2._Fld679RRef, T2._Fld680RRef, T2._Fld681RRef, T2._Fld682RRef, T2._Fld683RRef HAVING (CAST(SUM(T2._Fld684) AS NUMERIC(22, 2))) <> 0.0) T1',N'P1 datetime2(3),@P2 varbinary(16),@P3 numeric(10),@P4 numeric(10)','5999-11-01 00:00:00',0x811F000D3A223D1B11E6056572D76893,0,0 |
|||
129
H A D G E H O G s
20.06.18
✎
19:40
|
Проблема, скорее всего как раз в секциях. Он видит секции и начинает в них шарить, несмотря на индекс.
|
|||
130
vs84
20.06.18
✎
20:15
|
(0) а если в отборе не 50 тыс, а 1 тыс - план аналогичный?
|
|||
131
VitShvets
20.06.18
✎
20:23
|
(122) Это решается вьюхами. 1С спокойно себе работает с таблицами и не знает про вьюхи. Перенос данных спокойно себе работает со вьюхами и не знает про таблицы. Даже если 1С что-то поменяет в структуре хранения, актуализируем вьюхи, продолжаем работать.
(129) Сиквел хитро работает с секциями, они указаны в дереве индексов. В моём случае, т.к. он трогает все секции, я не получаю выигрыша от секционирования, "трогается" вся таблица, но по первому полю в индексе отбираются строки где Period = '5999-11-01'. |
|||
132
H A D G E H O G s
20.06.18
✎
20:28
|
Почему трогаются все секции?
|
|||
133
VitShvets
20.06.18
✎
20:30
|
(130) На сколько я понял по тестам, ключевое отличие тут равенство или другое условие. Если взять пример (128), и предположить, что организация есть второе поле кластерного индекса после периода, то запрос:
РегистрНакопления.ТоварыНаСкладах.Остатки(, Организация = &Организация) Полностью покроется кластерным индексом. Без дополнительных inner join. У меня же условие выглядит как: РегистрНакопления.МойРегистр.Остатки(, ЗаказПокупателя В (ВЫБРАТЬ ВТ1.ЗаказПокупателя ИЗ ВТ1)) Где ВТ1 таблица в одно поле, 50 тысяч записей, только ссылки на заказы. И тут уже план другой получается. Поднимается по кластерному записи только по периоду, а потом иннер-джоинятся уже с ВТ1. |
|||
134
VitShvets
20.06.18
✎
20:32
|
(132) :) Я собственно ради решения этого вопроса и тему создал. Причём берешь 1Совый запрос, меняешь совсем чуть-чуть, получаешь даже не тех-же самых данных кардинально иной результат.
|
|||
135
H A D G E H O G s
20.06.18
✎
21:07
|
(133) Вот мы и стали ближе к истине на 1 шаг.
Есть же теперь понимание того, что РегистрНакопления.МойРегистр.Остатки(, ЗаказПокупателя В (ВЫБРАТЬ ВТ1.ЗаказПокупателя ИЗ ВТ1)) использует индекс только по Периоду, без участия в нем ЗаказПокупателя ? |
|||
136
H A D G E H O G s
20.06.18
✎
21:49
|
Хех.
Сделал секционирование, как у автора и нарвался на его проблему. |
|||
137
H A D G E H O G s
20.06.18
✎
21:49
|
Щас Дима разберется.
|
|||
138
H A D G E H O G s
20.06.18
✎
22:02
|
Как только в запросе начинают использоваться параметры - секционирование не работает
|
|||
139
H A D G E H O G s
20.06.18
✎
22:04
|
Секционирование работает:
exec sp_executesql N'SELECT T1.Fld671RRef, T1.Fld672RRef, T1.Fld673RRef, T1.Fld674RRef, T1.Fld675RRef, T1.Fld863_, T1.Fld676Balance_ FROM (SELECT T2._Fld673RRef AS Fld673RRef, T2._Fld675RRef AS Fld675RRef, T2._Fld671RRef AS Fld671RRef, T2._Fld672RRef AS Fld672RRef, T2._Fld674RRef AS Fld674RRef, T2._Fld863 AS Fld863_, CAST(SUM(T2._Fld676) AS NUMERIC(27, 3)) AS Fld676Balance_ FROM dbo._AccumRgT677 T2 WHERE T2._Period = ''59991101 00:00:00.000'' AND ((T2._Fld671RRef = 0x810E000D3A22309E11E5EC30EF6782BC)) AND (T2._Fld676 <> 0) AND (T2._Fld676 <> 0) GROUP BY T2._Fld673RRef, T2._Fld675RRef, T2._Fld671RRef, T2._Fld672RRef, T2._Fld674RRef, T2._Fld863 HAVING (CAST(SUM(T2._Fld676) AS NUMERIC(27, 3))) <> 0.0) T1',N'@P1 datetime2(3),@P2 varbinary(16),@P3 numeric(10),@P4 numeric(10)','5999-11-01 00:00:00',0x811F000D3A223D1B11E6056572D76893,0,0 |
|||
140
H A D G E H O G s
20.06.18
✎
22:05
|
Секционирование не работает:
exec sp_executesql N'SELECT T1.Fld671RRef, T1.Fld672RRef, T1.Fld673RRef, T1.Fld674RRef, T1.Fld675RRef, T1.Fld863_, T1.Fld676Balance_ FROM (SELECT T2._Fld673RRef AS Fld673RRef, T2._Fld675RRef AS Fld675RRef, T2._Fld671RRef AS Fld671RRef, T2._Fld672RRef AS Fld672RRef, T2._Fld674RRef AS Fld674RRef, T2._Fld863 AS Fld863_, CAST(SUM(T2._Fld676) AS NUMERIC(27, 3)) AS Fld676Balance_ FROM dbo._AccumRgT677 T2 WHERE T2._Period = P1 AND ((T2._Fld671RRef = @P2)) AND (T2._Fld676 <> @P3) AND (T2._Fld676 <> @P4) GROUP BY T2._Fld673RRef, T2._Fld675RRef, T2._Fld671RRef, T2._Fld672RRef, T2._Fld674RRef, T2._Fld863 HAVING (CAST(SUM(T2._Fld676) AS NUMERIC(27, 3))) <> 0.0) T1',N'P1 datetime2(3),@P2 varbinary(16),@P3 numeric(10),@P4 numeric(10)','5999-11-01 00:00:00',0x811F000D3A223D1B11E6056572D76893,0,0 |
|||
141
H A D G E H O G s
20.06.18
✎
22:07
|
Я бы на месте автора сходил бы на sql.ru, там бы сразу ответили, думаю.
|
|||
142
H A D G E H O G s
20.06.18
✎
22:07
|
С примерами из 139 -140
|
|||
143
Genayo
20.06.18
✎
22:12
|
(140)Интересно, что было бы на постгресе...
|
|||
144
H A D G E H O G s
20.06.18
✎
22:13
|
В 139 префикс поиска ptnid1000=1
В 140 префикс поиска ptnid1000>=1 и ptnid1000<=3 |
|||
145
H A D G E H O G s
20.06.18
✎
22:13
|
Собственно, у меня 3 секции
|
|||
146
H A D G E H O G s
20.06.18
✎
22:14
|
||||
147
H A D G E H O G s
20.06.18
✎
22:15
|
||||
148
H A D G E H O G s
20.06.18
✎
22:22
|
Немного не то, у товарища в условии - функция.
|
|||
149
H A D G E H O G s
20.06.18
✎
22:34
|
||||
151
Антон Долгов
20.06.18
✎
23:12
|
(149) т.е. ты слился?
|
|||
152
H A D G E H O G s
20.06.18
✎
23:16
|
(151) system, ты не выеживайся, расскажи лучше нам, почему ты до этого сам не дошел.
|
|||
153
H A D G E H O G s
20.06.18
✎
23:17
|
(151) Ну и статью почитай, про динамическую фильтрацию.
|
|||
154
Антон Долгов
20.06.18
✎
23:17
|
Вот интересно, какой-то чувак из Волгограда чота прочитал где-то про что-то и решил это у себя попробовать. Ок, ему простительно, он из региона и всё такое. Но ты-то Ежов, ты же сертифицированный иксперд, как ты повелся на невнятное блеяние и начал потакать хотелкам нуба?
|
|||
155
H A D G E H O G s
модератор
20.06.18
✎
23:18
|
Давай, до свидания.
|
|||
158
breezee
21.06.18
✎
03:06
|
(5) Ага, на ура...
Выбрать в () будет работать очень медленно. Если нужно обрезать данные, то лучше использовать внутреннее соединение |
|||
159
nicxxx
21.06.18
✎
08:53
|
(158) Дело не в том, как ты напишешь код запроса, а в том, какой оптимизатор построит план. Он может построить одинаковый план для inner join и in ().
|
|||
160
ERWINS
21.06.18
✎
09:51
|
РегистрНакопления.МойРегистр.Остатки(, ЗаказПокупателя В (ВЫБРАТЬ ВТ1.ЗаказПокупателя ИЗ ВТ1))
в часто приводит к скану. Лучше РегистрНакопления.МойРегистр.Остатки(, ЗаказПокупателя = &знаение) если одно значение, тогда вроде он ВСЕГДА использует индекс сик Кроме того попробуйте сделать для ВТ1 индекс по заказу, тогда возможен индекс мердж |
|||
161
toypaul
гуру
21.06.18
✎
10:00
|
"Недокументировано" лезешь в базу и хочешь чтобы 1С тебя поняла? Будь готов к тому что не поймет и "отказаться от запросов 1С"
"Есть идеи как можно повлиять на РегистрНакопления.МойРегистр.Остатки ?" есть. написать в 1С, чтобы они учли это в новых релизах |
|||
162
toypaul
гуру
21.06.18
✎
10:01
|
exec sp_executesql('.....
.... FROM dbo._AccumRgT27531 T2 WITH(NOLOCK) WHERE T2._Period = P1 .....' P1 datetime2(3).... '5999-11-01 00:00:00' я правильно понимаю что 1С генерит несколько таких запросов вместо одного? пуская и с sp_executesql. или запрос один и все портит sp_executesql? |
|||
163
VitShvets
21.06.18
✎
12:21
|
Уххх, какая ожесточенная схватка :) А Антон Долгов, это такой местный сумасшедший? Обижаться нельзя, ибо на таких обижаться непрактично?
(139), (140) Именно так. А круче всего результат получается, если во времянку-условие добавить ещё константное поле Период со значением '5999-11-01 00:00:00' и сделать inner join по заказу+периоду с таблицей итогов. На моих данных, сейчас 0.5 секунды против 12 без секций и 6-7 секунд с секцями. |
|||
164
VitShvets
21.06.18
✎
12:25
|
(144) схожу, правда мне кажется, что там сходу посоветуют как надо запрос переписать, чтобы секции сработали. А я это и так уже знаю. Мне бы 1С заставить каким-то хитрым способом объяснить сиквелу... Но схожу. Коли будет результат, сюда отпишусь.
|
|||
165
VitShvets
21.06.18
✎
12:30
|
(158), (159) Inner join хорошо срабатывает когда соединяется с физической таблицей. Виртуальная таблица, это "select ... from (select ..." и join будет с внешним select... Т.е. отбора по заказам, в моём случае, не будет на уровне выборки из таблицы итогов.
|
|||
166
VitShvets
21.06.18
✎
12:33
|
(160) Понятно, что "ЗаказПокупателя = &знаение" будет лучше, но мне то надо по списку заказов.
Я индексирую ВТ, но у меня на времянке индекс скан получается. |
|||
167
H A D G E H O G s
21.06.18
✎
12:35
|
(166) Ты же понимаешь, что ты делаешь фигню?
|
|||
168
VitShvets
21.06.18
✎
12:36
|
(161) Я вот как раз и сопротивляюсь до последнего "недокументированному лазанью" в базу. Хочется минимальными затратами получить максимальный профит. Как обычно впрочем.
|
|||
169
VitShvets
21.06.18
✎
12:40
|
(162) 1С генерирует один запрос. Всё портит "sp_executesql", а точнее то, что оптимизатор при построении плана не учитывает значение параметров. Не уверен что это именно оно, но очень похоже на "Parameter sniffing".
|
|||
170
VitShvets
21.06.18
✎
12:41
|
(167) Ты про индексирование? Я не увидел разницу с индексами и без. По крайней мере по запросам, что рождает 1С. Это тесты всё.
|
|||
171
VitShvets
21.06.18
✎
12:43
|
(167) Есть кстати жгучее желание испить немного пенных напитков и обсудить ряд жизненноважных проблем :)
|
|||
172
Genayo
21.06.18
✎
13:03
|
(170) На 50000 записей и не увидишь...
|
|||
173
H A D G E H O G s
21.06.18
✎
13:05
|
(170) Именно.
Если ВТ велика (больше 1000 строк, конкретное значение уж не помню) - SQL не использует индекс при соединении. Ведь, чтобы использовать индекс - нужен nested loops - проход по строкам временной таблицы и для каждой строки временной таблицы - индексный поиск в виртуальной. Если строк ВТ будет много - SQL может посчитать, что проще обойти обе таблицы через mergejoin. |
|||
174
H A D G E H O G s
21.06.18
✎
13:07
|
mergejoin будет еще более вероятен, если ВТ и Виртуальная таблицы индекскированы. Но не из-за индекса, а из-за того, что таблицы УПОРЯДОЧЕНЫ по полю поиска из за наличия этого индекса.
Но, упорядочить ВТ можно, не создавая Индекс, а отсортировав, что более дешево. Индекс опять не нужен, НО. |
|||
175
H A D G E H O G s
21.06.18
✎
13:07
|
В вашем примере mergejoin использован не будет
|
|||
176
H A D G E H O G s
21.06.18
✎
13:10
|
Ибо, чтобы использовать mergejoin, нужно 2 таблицы, которых у вас пока нет, пока не выполниться поиск по Периоду из таблицы остатков.
По идее, если задать хинт на использование mergejoin, то SQL выполнит TableSpool (сохранение промежуточной таблицы в tempDB, фактически, та же временная таблица, средствами SQL) для результата отбора по периоду для таблицы остатков, дико медленную и потом сделает mergejoin с вашей временной. |
|||
177
H A D G E H O G s
21.06.18
✎
13:10
|
Поэтому, SQL сделает HashJoin
|
|||
178
H A D G E H O G s
21.06.18
✎
13:12
|
SQL построит хэштаблицу для вашей временной таблицы, затем выберет записи из таблицы остатков по периоду и обойдет эти записи, ища их строки в хэштаблице.
|
|||
179
los_hooliganos
21.06.18
✎
13:15
|
(169) Все верно. Построитель запроса не знает параметров, поэтому строит план запроса на все секции.
|
|||
180
los_hooliganos
21.06.18
✎
13:20
|
Я бы сделал вьюху с таким вот условием:
WHERE case T2._Period = '2001-01-01 00:00:00' and '2002-01-01 00:00:00' and $PARTITION.partition_function(_Period) = 2001 then true Секционирование заработает и особо извращаться не надо и построитель запроса все должен учесть. |
|||
181
los_hooliganos
21.06.18
✎
13:21
|
(180) ну ес-но в CASE сам пропиши соотношения периодов и секций
|
|||
182
los_hooliganos
21.06.18
✎
13:23
|
точнее :)
WHERE case when view.Period between '2001-01-01 00:00:00' and '2002-01-01 00:00:00' and $PARTITION.partition_function(Period) = 2001 then true when ... then end |
|||
183
VitShvets
21.06.18
✎
13:30
|
(177), (178) У меня mergejoin получается во всех вариантах.
|
|||
184
H A D G E H O G s
21.06.18
✎
13:48
|
(183) значит я что-то не учел.
|
|||
185
Fragster
гуру
21.06.18
✎
14:27
|
получается автору надо поместить остатки в ВТ, а потом её уже отбирать.
|
|||
186
H A D G E H O G s
21.06.18
✎
14:50
|
(183) Воспроизвел твою ситуацию - HashMatch
|
|||
187
H A D G E H O G s
21.06.18
✎
14:54
|
Однако я ошибся с 1000 строк ВТ.
У меня ВТ была на 30Кстрок (при 8млн. строк таблицы остатков) - был nested_loops. 30 тыс поисков по индексу в таблице остатков. Увеличил ВТ до 80Кстрок - стал hash_join. Видимо, есть какое то отношение размера внешней и внутренней таблицы. |
|||
188
VitShvets
21.06.18
✎
16:54
|
(185) Выигрыша не будет. Это тоже самое, что получить все оперативные остатки.
|
|||
189
VitShvets
21.06.18
✎
16:55
|
(186) У меня есть TRC, где в одном случае нестед лупс есть, но взял сейчас тот запрос, не получатся повторить, везде mergejoin...
|
|||
190
VitShvets
21.06.18
✎
16:56
|
(187) Вот тоже такое ощущение. Сейчас записей меньше стало, планы поменялись.
|
|||
192
Fragster
гуру
21.06.18
✎
17:07
|
(188) ну так веь ты говоришь, что у тебя все секции дергаются. а это не только оперативные остатки, но и помесячные итоги, которых в несколько (десятков) раз больше
|
|||
193
VitShvets
21.06.18
✎
17:13
|
(191) Ты зря перестал принимать такие кругленькие штучки, что тётя доктор прописала. Береги себя.
|
|||
194
VitShvets
21.06.18
✎
17:21
|
(192) Дёргаются, да, но по дереву индексов всёравно я получаю оперативные итоги, что на следующем шаге иннер джоянятся mergejoin-ом с времянкой-фильтром. Как итог, с сервера вытягиваются данные только по 50 тысячам заказов. Если делать внутреннее соединение с виртуальной таблицей или складывать остатки во времянку, а потом соединять две времянки, будет как минимум дольше на вытягивание всех итогов и/или создание временной таблицы.
|
|||
195
МихаилМ
25.06.18
✎
23:26
|
еще можно попробовать
https://msdn.microsoft.com/ru-ru/uk-an/library/ms179880(v=sql.120).aspx |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |